[mach-o] add support for old x86 __eh_frame sections

Over time the symbols and relocations have changed for dwarf unwind info
in the __eh_frame section.  Add test cases for older and new style.

llvm-svn: 213585
This commit is contained in:
Nick Kledzik 2014-07-21 22:06:57 +00:00
parent 586448763e
commit 03e16f2ab4
4 changed files with 369 additions and 27 deletions

View File

@ -83,6 +83,7 @@ private:
funcRel32, /// ex: movl _foo-L1(%eax), %eax
pointer32, /// ex: .long _foo
delta32, /// ex: .long _foo - .
negDelta32, /// ex: .long . - _foo
// Kinds introduced by Passes:
lazyPointer, /// Location contains a lazy pointer.
@ -120,6 +121,7 @@ const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(funcRel32),
LLD_KIND_STRING_ENTRY(pointer32),
LLD_KIND_STRING_ENTRY(delta32),
LLD_KIND_STRING_ENTRY(negDelta32),
LLD_KIND_STRING_ENTRY(lazyPointer),
LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
LLD_KIND_STRING_END
@ -302,22 +304,28 @@ ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
if (ec)
return ec;
if (fromTarget != inAtom)
return make_dynamic_error_code(Twine("SECTDIFF relocation where "
"subtrahend label is not in atom"));
*kind = ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? funcRel32
: delta32;
if (*kind == funcRel32) {
// SECTDIFF relocations are used in i386 codegen where the function
// prolog does a CALL to the next instruction which POPs the return
// address into EBX which becomes the pic-base register. The POP
// instruction is label the used for the subtrahend in expressions.
// The funcRel32 kind represents the 32-bit delta to some symbol from
// the start of the function (atom) containing the funcRel32.
uint32_t ta = fromAddress + value - toAddress;
*addend = ta - offsetInFrom;
if (fromTarget != inAtom) {
if (*target != inAtom)
return make_dynamic_error_code(Twine("SECTDIFF relocation where "
"neither target is in atom"));
*kind = negDelta32;
*addend = toAddress - value - fromAddress;
*target = fromTarget;
} else {
*addend = fromAddress + value - toAddress;
if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) {
// SECTDIFF relocations are used in i386 codegen where the function
// prolog does a CALL to the next instruction which POPs the return
// address into EBX which becomes the pic-base register. The POP
// instruction is label the used for the subtrahend in expressions.
// The funcRel32 kind represents the 32-bit delta to some symbol from
// the start of the function (atom) containing the funcRel32.
*kind = funcRel32;
uint32_t ta = fromAddress + value - toAddress;
*addend = ta - offsetInFrom;
} else {
*kind = delta32;
*addend = fromAddress + value - toAddress;
}
}
return std::error_code();
break;
@ -379,6 +387,9 @@ void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *location,
case delta32:
write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
break;
case negDelta32:
write32(*loc32, _swap, fixupAddress - targetAddress + ref.addend());
break;
case lazyPointer:
case lazyImmediateLocation:
// do nothing
@ -420,6 +431,9 @@ void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
case delta32:
write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
break;
case negDelta32:
write32(*loc32, _swap, fixupAddress - targetAddress + ref.addend());
break;
case lazyPointer:
case lazyImmediateLocation:
// do nothing
@ -507,17 +521,24 @@ void ArchHandler_x86::appendSectionRelocations(
}
break;
case funcRel32:
appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
GENERIC_RELOC_PAIR | rScattered | rLength4);
appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
GENERIC_RELOC_PAIR | rScattered | rLength4);
break;
case delta32:
appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
ref.offsetInAtom(),
GENERIC_RELOC_PAIR | rScattered | rLength4);
appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
ref.offsetInAtom(),
GENERIC_RELOC_PAIR | rScattered | rLength4);
break;
case negDelta32:
appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
ref.offsetInAtom(),
GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
GENERIC_RELOC_PAIR | rScattered | rLength4);
break;
case lazyPointer:
case lazyImmediateLocation:

View File

@ -62,6 +62,7 @@ const MachORelocatableSectionToAtomType sectsToAtomType[] = {
ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
ENTRY("__TEXT", "__const_coal", S_COALESCED, typeConstant),
ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI),
ENTRY("__TEXT", "__eh_frame", S_REGULAR, typeCFI),
ENTRY("__TEXT", "__literal4", S_4BYTE_LITERALS, typeLiteral4),
ENTRY("__TEXT", "__literal8", S_8BYTE_LITERALS, typeLiteral8),
ENTRY("__TEXT", "__literal16", S_16BYTE_LITERALS, typeLiteral16),
@ -149,7 +150,7 @@ void sectionParseInfo(DefinedAtom::ContentType atomType,
atomizeUTF8),
ENTRY(typeUTF16String, 1, scopeLinkageUnit, mergeByContent,
atomizeUTF16),
ENTRY(typeCFI, 1, scopeTranslationUnit, mergeNo,
ENTRY(typeCFI, 4, scopeTranslationUnit, mergeNo,
atomizeCFI),
ENTRY(typeLiteral4, 4, scopeLinkageUnit, mergeByContent,
atomizeFixedSize),
@ -165,8 +166,6 @@ void sectionParseInfo(DefinedAtom::ContentType atomType,
atomizePointerSize),
ENTRY(typeCompactUnwindInfo, 4, scopeTranslationUnit, mergeNo,
atomizeCU),
ENTRY(typeCFI, 4, scopeTranslationUnit, mergeNo,
atomizeFixedSize),
ENTRY(typeGOT, 4, scopeLinkageUnit, mergeByContent,
atomizePointerSize),
ENTRY(typeUnknown, 1, scopeGlobal, mergeNo,

View File

@ -0,0 +1,129 @@
# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t | FileCheck %s
#
# Test parsing of new __eh_frame (dwarf unwind) section that has no .eh labels
# and no relocations.
#
--- !mach-o
arch: x86
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
OS: unknown
sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
0xBC, 0xFF, 0xFF, 0xFF ]
relocations:
- offset: 0x00000040
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: false
symbol: 1
- offset: 0x00000035
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: true
symbol: 4
- offset: 0x00000021
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
length: 2
pc-rel: false
value: 0x00000044
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x0000000C
- offset: 0x00000015
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: true
symbol: 3
- segment: __IMPORT
section: __pointers
type: S_NON_LAZY_SYMBOL_POINTERS
attributes: [ ]
address: 0x0000000000000044
content: [ 0x00, 0x00, 0x00, 0x00 ]
indirect-syms: [ 5 ]
- segment: __TEXT
section: __eh_frame
type: S_REGULAR
attributes: [ ]
alignment: 2
address: 0x0000000000000048
content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
0x84, 0x02, 0x42, 0x0D, 0x04, 0x00, 0x00, 0x00 ]
global-symbols:
- name: __Z3barv
type: N_SECT
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000039
- name: __Z3foov
type: N_SECT
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000000
undefined-symbols:
- name: __ZTIi
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
- name: ___cxa_allocate_exception
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
- name: ___cxa_throw
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
...
# CHECK: defined-atoms:
# FIXME: - ref-name: [[CIE:L[L0-9]+]]
# CHECK: type: unwind-cfi
# CHECK: content:
# CHECK: - type: unwind-cfi
# CHECK: content:
# FIXME: references:
# FIXME: - kind: negDelta32
# FIXME: offset: 4
# FIXME: target: [[CIE]]
# FIXME: - kind: delta32
# FIXME: offset: 8
# FIXME: target: __Z3foov
# CHECK: - type: unwind-cfi
# CHECK: content:
# FIXME: references:
# FIXME: - kind: negDelta32
# FIXME: offset: 4
# FIXME: target: [[CIE]]
# FIXME: - kind: delta32
# FIXME: offset: 8
# FIXME: target: __Z3barv

View File

@ -0,0 +1,193 @@
# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t | FileCheck %s
#
# Test parsing of old __eh_frame (dwarf unwind) section that has .eh labels
# and relocations.
#
--- !mach-o
arch: x86
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
OS: unknown
sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
0xBC, 0xFF, 0xFF, 0xFF ]
relocations:
- offset: 0x00000040
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: false
symbol: 1
- offset: 0x00000035
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: true
symbol: 7
- offset: 0x00000021
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
length: 2
pc-rel: false
value: 0x00000044
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x0000000C
- offset: 0x00000015
type: GENERIC_RELOC_VANILLA
length: 2
pc-rel: true
extern: true
symbol: 6
- segment: __IMPORT
section: __pointers
type: S_NON_LAZY_SYMBOL_POINTERS
attributes: [ ]
address: 0x0000000000000044
content: [ 0x00, 0x00, 0x00, 0x00 ]
indirect-syms: [ 5 ]
- segment: __TEXT
section: __eh_frame
type: S_REGULAR
attributes: [ ]
alignment: 2
address: 0x0000000000000048
content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
0x84, 0x02, 0x42, 0x0D, 0x04, 0x00, 0x00, 0x00 ]
relocations:
- offset: 0x0000001C
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
length: 2
pc-rel: false
value: 0x00000064
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x00000048
- offset: 0x00000020
scattered: true
type: GENERIC_RELOC_SECTDIFF
length: 2
pc-rel: false
value: 0x00000000
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x00000068
- offset: 0x00000038
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
length: 2
pc-rel: false
value: 0x00000080
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x00000048
- offset: 0x0000003C
scattered: true
type: GENERIC_RELOC_SECTDIFF
length: 2
pc-rel: false
value: 0x00000039
- offset: 0x00000000
scattered: true
type: GENERIC_RELOC_PAIR
length: 2
pc-rel: false
value: 0x00000084
local-symbols:
- name: EH_frame0
type: N_SECT
sect: 3
value: 0x0000000000000048
global-symbols:
- name: __Z3barv
type: N_SECT
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000039
- name: __Z3barv.eh
type: N_SECT
scope: [ N_EXT ]
sect: 3
value: 0x000000000000007C
- name: __Z3foov
type: N_SECT
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000000
- name: __Z3foov.eh
type: N_SECT
scope: [ N_EXT ]
sect: 3
value: 0x0000000000000060
undefined-symbols:
- name: __ZTIi
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
- name: ___cxa_allocate_exception
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
- name: ___cxa_throw
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
...
# CHECK: defined-atoms:
# CHECK: - ref-name: [[CIE:L[L0-9]+]]
# CHECK: type: unwind-cfi
# CHECK: content:
# CHECK: - type: unwind-cfi
# CHECK: content:
# CHECK: references:
# CHECK: - kind: negDelta32
# CHECK: offset: 4
# CHECK: target: [[CIE]]
# CHECK: - kind: delta32
# CHECK: offset: 8
# CHECK: target: __Z3foov
# CHECK: - type: unwind-cfi
# CHECK: content:
# CHECK: references:
# CHECK: - kind: negDelta32
# CHECK: offset: 4
# CHECK: target: [[CIE]]
# CHECK: - kind: delta32
# CHECK: offset: 8
# CHECK: target: __Z3barv