diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp index b54c00eb409a..cfd30d98de4c 100644 --- a/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp +++ b/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp @@ -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: diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index cc0289e33448..ef6f49f79318 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -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, diff --git a/lld/test/mach-o/parse-eh-frame-x86-anon.yaml b/lld/test/mach-o/parse-eh-frame-x86-anon.yaml new file mode 100644 index 000000000000..088f14d5cec7 --- /dev/null +++ b/lld/test/mach-o/parse-eh-frame-x86-anon.yaml @@ -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 + diff --git a/lld/test/mach-o/parse-eh-frame-x86-labeled.yaml b/lld/test/mach-o/parse-eh-frame-x86-labeled.yaml new file mode 100644 index 000000000000..b07a534e6493 --- /dev/null +++ b/lld/test/mach-o/parse-eh-frame-x86-labeled.yaml @@ -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 +