[mach-o] Add support for x86 CALL instruction that uses a scattered relocation

llvm-svn: 213340
This commit is contained in:
Nick Kledzik 2014-07-18 00:37:52 +00:00
parent 1eb023013e
commit 68a1abdf14
2 changed files with 157 additions and 60 deletions

View File

@ -202,6 +202,14 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
break;
case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
// ex: call _foo+n (and _foo defined)
*kind = branch32;
targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
if (E ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
*addend = targetAddress - reloc.value;
break;
case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
// ex: callw _foo (and _foo undefined)
*kind = branch16;
@ -215,6 +223,14 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
break;
case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
// ex: callw _foo+n (and _foo defined)
*kind = branch16;
targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
if (E ec = atomFromAddress(0, reloc.value, target, addend))
return ec;
*addend = targetAddress - reloc.value;
break;
case GENERIC_RELOC_VANILLA | rExtern | rLength4:
// ex: movl _foo, %eax (and _foo undefined)
// ex: .long _foo (and _foo undefined)
@ -370,12 +386,19 @@ void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
uint64_t inAtomAddress) {
int32_t *loc32 = reinterpret_cast<int32_t *>(location);
int16_t *loc16 = reinterpret_cast<int16_t *>(location);
bool useExternalReloc = useExternalRelocationTo(*ref.target());
switch (ref.kindValue()) {
case branch32:
write32(*loc32, _swap, ref.addend() - (fixupAddress + 4));
if (useExternalReloc)
write32(*loc32, _swap, ref.addend() - (fixupAddress + 4));
else
write32(*loc32, _swap, (targetAddress - (fixupAddress+4)) + ref.addend());
break;
case branch16:
write16(*loc16, _swap, ref.addend() - (fixupAddress + 2));
if (useExternalReloc)
write16(*loc16, _swap, ref.addend() - (fixupAddress + 2));
else
write16(*loc16, _swap, (targetAddress - (fixupAddress+2)) + ref.addend());
break;
case pointer32:
case abs32:
@ -434,20 +457,30 @@ void ArchHandler_x86::appendSectionRelocations(
bool useExternalReloc = useExternalRelocationTo(*ref.target());
switch (ref.kindValue()) {
case branch32:
if (useExternalReloc)
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4);
else
appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
GENERIC_RELOC_VANILLA | rPcRel | rLength4);
if (useExternalReloc) {
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength4);
} else {
if (ref.addend() != 0)
appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4);
else
appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
GENERIC_RELOC_VANILLA | rPcRel | rLength4);
}
break;
case branch16:
if (useExternalReloc)
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2);
else
appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
GENERIC_RELOC_VANILLA | rPcRel | rLength2);
if (useExternalReloc) {
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength2);
} else {
if (ref.addend() != 0)
appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2);
else
appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
GENERIC_RELOC_VANILLA | rPcRel | rLength2);
}
break;
case pointer32:
case abs32:

View File

@ -12,16 +12,24 @@
#_test:
# call _undef
# call _undef+2
# call _foo
# call _foo+2
# callw _undef
# callw _foo
# callw _foo+2
#L1:
# movl _undef, %eax
# movl _x, %eax
# movl _x-L1(%eax), %eax
# movl _x+4-L1(%eax), %eax
#
#_foo:
# ret
#
# .data
#_x:
# .long _undef
# .long _foo
# .long _test - .
# .long _test+3 - .
#
@ -29,7 +37,7 @@
--- !mach-o
arch: x86
file-type: MH_OBJECT
flags: [ ]
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
OS: unknown
sections:
- segment: __TEXT
@ -38,73 +46,111 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
content: [ 0xE8, 0xFB, 0xFF, 0xFF, 0xFF, 0xE8, 0xF8, 0xFF,
0xFF, 0xFF, 0x66, 0xE8, 0xF2, 0xFF, 0xA1, 0x00,
0x00, 0x00, 0x00, 0xA1, 0x24, 0x00, 0x00, 0x00,
0x8B, 0x80, 0x16, 0x00, 0x00, 0x00, 0x8B, 0x80,
0x1A, 0x00, 0x00, 0x00 ]
0xFF, 0xFF, 0xE8, 0x27, 0x00, 0x00, 0x00, 0xE8,
0x24, 0x00, 0x00, 0x00, 0x66, 0xE8, 0xE8, 0xFF,
0x66, 0xE8, 0x1A, 0x00, 0x66, 0xE8, 0x18, 0x00,
0xA1, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x37, 0x00,
0x00, 0x00, 0x8B, 0x80, 0x17, 0x00, 0x00, 0x00,
0x8B, 0x80, 0x1B, 0x00, 0x00, 0x00, 0xC3 ]
relocations:
- offset: 0x00000020
- offset: 0x00000032
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
length: 2
pc-rel: false
value: 0x00000024
value: 0x00000037
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x0000000E
- offset: 0x0000001A
value: 0x00000020
- offset: 0x0000002C
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
length: 2
pc-rel: false
value: 0x00000024
value: 0x00000037
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x0000000E
- offset: 0x00000014
value: 0x00000020
- offset: 0x00000026
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: false
extern: false
symbol: 2
- offset: 0x0000000F
- offset: 0x00000021
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: false
extern: true
symbol: 2
- offset: 0x0000000C
symbol: 3
- offset: 0x0000001E
scattered: true
type: GENERIC_RELOC_VANILLA
length: 1
pc-rel: true
value: 0x00000036
- offset: 0x0000001A
type: GENERIC_RELOC_VANILLA
length: 1
pc-rel: true
extern: false
symbol: 1
- offset: 0x00000016
type: GENERIC_RELOC_VANILLA
length: 1
pc-rel: true
extern: true
symbol: 2
symbol: 3
- offset: 0x00000010
scattered: true
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
value: 0x00000036
- offset: 0x0000000B
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: false
symbol: 1
- offset: 0x00000006
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: true
symbol: 2
symbol: 3
- offset: 0x00000001
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: true
symbol: 2
symbol: 3
- segment: __DATA
section: __data
type: S_REGULAR
attributes: [ ]
address: 0x0000000000000024
content: [ 0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xFF, 0xFF,
0xD7, 0xFF, 0xFF, 0xFF ]
address: 0x0000000000000037
content: [ 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
0xC1, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF ]
relocations:
- offset: 0x0000000C
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
length: 2
pc-rel: false
value: 0x00000000
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x00000043
- offset: 0x00000008
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
@ -116,34 +162,32 @@ sections:
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x0000002C
value: 0x0000003F
- offset: 0x00000004
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: false
value: 0x00000000
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x00000028
extern: false
symbol: 1
- offset: 0x00000000
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: false
extern: true
symbol: 2
symbol: 3
local-symbols:
- name: _test
type: N_SECT
sect: 1
value: 0x0000000000000000
- name: _foo
type: N_SECT
sect: 1
value: 0x0000000000000036
- name: _x
type: N_SECT
sect: 2
value: 0x0000000000000024
value: 0x0000000000000037
undefined-symbols:
- name: _undef
type: N_UNDF
@ -158,12 +202,15 @@ undefined-symbols:
# CHECK: - kind: pointer32
# CHECK: offset: 0
# CHECK: target: _undef
# CHECK: - kind: delta32
# CHECK: - kind: pointer32
# CHECK: offset: 4
# CHECK: target: _test
# CHECK: target: _foo
# CHECK: - kind: delta32
# CHECK: offset: 8
# CHECK: target: _test
# CHECK: - kind: delta32
# CHECK: offset: 12
# CHECK: target: _test
# CHECK: addend: 3
# CHECK: - name: _test
# CHECK: references:
@ -175,21 +222,38 @@ undefined-symbols:
# CHECK: offset: 6
# CHECK: target: _undef
# CHECK: addend: 2
# CHECK: - kind: branch32
# CHECK: offset: 11
# CHECK: target: _foo
# CHECK-NOT: addend:
# CHECK: - kind: branch32
# CHECK: offset: 16
# CHECK: target: _foo
# CHECK: addend: 2
# CHECK: - kind: branch16
# CHECK: offset: 12
# CHECK: offset: 22
# CHECK: target: _undef
# CHECK: - kind: abs32
# CHECK: offset: 15
# CHECK: target: _undef
# CHECK: - kind: abs32
# CHECK: offset: 20
# CHECK: target: _x
# CHECK: - kind: funcRel32
# CHECK-NOT: addend:
# CHECK: - kind: branch16
# CHECK: offset: 26
# CHECK: target: _foo
# CHECK-NOT: addend:
# CHECK: - kind: branch16
# CHECK: offset: 30
# CHECK: target: _foo
# CHECK: addend: 2
# CHECK: - kind: abs32
# CHECK: offset: 33
# CHECK: target: _undef
# CHECK: - kind: abs32
# CHECK: offset: 38
# CHECK: target: _x
# CHECK: addend: -14
# CHECK: - kind: funcRel32
# CHECK: offset: 32
# CHECK: offset: 44
# CHECK: target: _x
# CHECK: addend: -10
# CHECK: addend: -32
# CHECK: - kind: funcRel32
# CHECK: offset: 50
# CHECK: target: _x
# CHECK: addend: -28