diff options
Diffstat (limited to 'lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp')
| -rw-r--r-- | lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp | 113 |
1 files changed, 97 insertions, 16 deletions
diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp index 81fe1af42d7e..c57a00359e33 100644 --- a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp +++ b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp @@ -30,8 +30,8 @@ using llvm::support::little64_t; class ArchHandler_x86_64 : public ArchHandler { public: - ArchHandler_x86_64(); - virtual ~ArchHandler_x86_64(); + ArchHandler_x86_64() = default; + ~ArchHandler_x86_64() override = default; const Registry::KindStrings *kindStrings() override { return _sKindStrings; } @@ -59,6 +59,19 @@ public: } } + bool isTLVAccess(const Reference &ref) const override { + assert(ref.kindNamespace() == Reference::KindNamespace::mach_o); + assert(ref.kindArch() == Reference::KindArch::x86_64); + return ref.kindValue() == ripRel32Tlv; + } + + void updateReferenceToTLV(const Reference *ref) override { + assert(ref->kindNamespace() == Reference::KindNamespace::mach_o); + assert(ref->kindArch() == Reference::KindArch::x86_64); + assert(ref->kindValue() == ripRel32Tlv); + const_cast<Reference*>(ref)->setKindValue(ripRel32); + } + /// Used by GOTPass to update GOT References void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override { assert(ref->kindNamespace() == Reference::KindNamespace::mach_o); @@ -82,9 +95,11 @@ public: bool needsCompactUnwind() override { return true; } + Reference::KindValue imageOffsetKind() override { return imageOffset; } + Reference::KindValue imageOffsetKindIndirect() override { return imageOffsetGot; } @@ -168,8 +183,12 @@ private: ripRel32Minus2, /// ex: movw $0x1234, _foo(%rip) ripRel32Minus4, /// ex: movl $0x12345678, _foo(%rip) ripRel32Anon, /// ex: movq L1(%rip), %rax + ripRel32Minus1Anon, /// ex: movb $0x12, L1(%rip) + ripRel32Minus2Anon, /// ex: movw $0x1234, L1(%rip) + ripRel32Minus4Anon, /// ex: movw $0x12345678, L1(%rip) ripRel32GotLoad, /// ex: movq _foo@GOTPCREL(%rip), %rax ripRel32Got, /// ex: pushq _foo@GOTPCREL(%rip) + ripRel32Tlv, /// ex: movq _foo@TLVP(%rip), %rdi pointer64, /// ex: .quad _foo pointer64Anon, /// ex: .quad L1 delta64, /// ex: .quad _foo - . @@ -192,6 +211,8 @@ private: /// relocatable object (yay for implicit contracts!). unwindInfoToEhFrame, /// Fix low 24 bits of compact unwind encoding to /// refer to __eh_frame entry. + tlvInitSectionOffset /// Location contains offset tlv init-value atom + /// within the __thread_data section. }; Reference::KindValue kindFromReloc(const normalized::Relocation &reloc); @@ -209,18 +230,18 @@ private: uint64_t inAtomAddress); }; - -ArchHandler_x86_64::ArchHandler_x86_64() { } - -ArchHandler_x86_64::~ArchHandler_x86_64() { } - const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = { LLD_KIND_STRING_ENTRY(invalid), LLD_KIND_STRING_ENTRY(branch32), LLD_KIND_STRING_ENTRY(ripRel32), LLD_KIND_STRING_ENTRY(ripRel32Minus1), LLD_KIND_STRING_ENTRY(ripRel32Minus2), LLD_KIND_STRING_ENTRY(ripRel32Minus4), - LLD_KIND_STRING_ENTRY(ripRel32Anon), LLD_KIND_STRING_ENTRY(ripRel32GotLoad), + LLD_KIND_STRING_ENTRY(ripRel32Anon), + LLD_KIND_STRING_ENTRY(ripRel32Minus1Anon), + LLD_KIND_STRING_ENTRY(ripRel32Minus2Anon), + LLD_KIND_STRING_ENTRY(ripRel32Minus4Anon), + LLD_KIND_STRING_ENTRY(ripRel32GotLoad), LLD_KIND_STRING_ENTRY(ripRel32GotLoadNowLea), - LLD_KIND_STRING_ENTRY(ripRel32Got), LLD_KIND_STRING_ENTRY(lazyPointer), + LLD_KIND_STRING_ENTRY(ripRel32Got), LLD_KIND_STRING_ENTRY(ripRel32Tlv), + LLD_KIND_STRING_ENTRY(lazyPointer), LLD_KIND_STRING_ENTRY(lazyImmediateLocation), LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(pointer64Anon), LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(delta64), @@ -229,6 +250,7 @@ const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = { LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot), LLD_KIND_STRING_ENTRY(unwindFDEToFunction), LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame), + LLD_KIND_STRING_ENTRY(tlvInitSectionOffset), LLD_KIND_STRING_END }; @@ -301,14 +323,22 @@ ArchHandler_x86_64::kindFromReloc(const Relocation &reloc) { return ripRel32Anon; case X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4: return ripRel32Minus1; + case X86_64_RELOC_SIGNED_1 | rPcRel | rLength4: + return ripRel32Minus1Anon; case X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4: return ripRel32Minus2; + case X86_64_RELOC_SIGNED_2 | rPcRel | rLength4: + return ripRel32Minus2Anon; case X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4: return ripRel32Minus4; + case X86_64_RELOC_SIGNED_4 | rPcRel | rLength4: + return ripRel32Minus4Anon; case X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4: return ripRel32GotLoad; case X86_64_RELOC_GOT | rPcRel | rExtern | rLength4: return ripRel32Got; + case X86_64_RELOC_TLV | rPcRel | rExtern | rLength4: + return ripRel32Tlv; case X86_64_RELOC_UNSIGNED | rExtern | rLength8: return pointer64; case X86_64_RELOC_UNSIGNED | rLength8: @@ -331,7 +361,7 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc, typedef std::error_code E; *kind = kindFromReloc(reloc); if (*kind == invalid) - return make_dynamic_error_code(Twine("unknown type")); + return make_dynamic_error_code("unknown type"); const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; uint64_t targetAddress; switch (*kind) { @@ -359,16 +389,34 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc, case ripRel32Anon: targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); + case ripRel32Minus1Anon: + targetAddress = fixupAddress + 5 + *(const little32_t *)fixupContent; + return atomFromAddress(reloc.symbol, targetAddress, target, addend); + case ripRel32Minus2Anon: + targetAddress = fixupAddress + 6 + *(const little32_t *)fixupContent; + return atomFromAddress(reloc.symbol, targetAddress, target, addend); + case ripRel32Minus4Anon: + targetAddress = fixupAddress + 8 + *(const little32_t *)fixupContent; + return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ripRel32GotLoad: case ripRel32Got: + case ripRel32Tlv: if (E ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = *(const little32_t *)fixupContent; return std::error_code(); + case tlvInitSectionOffset: case pointer64: if (E ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; - *addend = *(const little64_t *)fixupContent; + // If this is the 3rd pointer of a tlv-thunk (i.e. the pointer to the TLV's + // initial value) we need to handle it specially. + if (inAtom->contentType() == DefinedAtom::typeThunkTLV && + offsetInAtom == 16) { + *kind = tlvInitSectionOffset; + assert(*addend == 0 && "TLV-init has non-zero addend?"); + } else + *addend = *(const little64_t *)fixupContent; return std::error_code(); case pointer64Anon: targetAddress = *(const little64_t *)fixupContent; @@ -413,7 +461,7 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1, Reference::Addend *addend) { *kind = kindFromRelocPair(reloc1, reloc2); if (*kind == invalid) - return make_dynamic_error_code(Twine("unknown pair")); + return make_dynamic_error_code("unknown pair"); const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; typedef std::error_code E; uint64_t targetAddress; @@ -421,7 +469,7 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1, if (E ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget)) return ec; if (fromTarget != inAtom) - return make_dynamic_error_code(Twine("pointer diff not in base atom")); + return make_dynamic_error_code("pointer diff not in base atom"); switch (*kind) { case delta64: if (E ec = atomFromSymbolIndex(reloc2.symbol, target)) @@ -486,19 +534,26 @@ void ArchHandler_x86_64::applyFixupFinal( case ripRel32Anon: case ripRel32Got: case ripRel32GotLoad: + case ripRel32Tlv: *loc32 = targetAddress - (fixupAddress + 4) + ref.addend(); return; case pointer64: case pointer64Anon: *loc64 = targetAddress + ref.addend(); return; + case tlvInitSectionOffset: + *loc64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend(); + return; case ripRel32Minus1: + case ripRel32Minus1Anon: *loc32 = targetAddress - (fixupAddress + 5) + ref.addend(); return; case ripRel32Minus2: + case ripRel32Minus2Anon: *loc32 = targetAddress - (fixupAddress + 6) + ref.addend(); return; case ripRel32Minus4: + case ripRel32Minus4Anon: *loc32 = targetAddress - (fixupAddress + 8) + ref.addend(); return; case delta32: @@ -542,7 +597,6 @@ void ArchHandler_x86_64::applyFixupFinal( llvm_unreachable("invalid x86_64 Reference Kind"); } - void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, @@ -558,11 +612,13 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, case ripRel32: case ripRel32Got: case ripRel32GotLoad: + case ripRel32Tlv: *loc32 = ref.addend(); return; case ripRel32Anon: *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend(); return; + case tlvInitSectionOffset: case pointer64: *loc64 = ref.addend(); return; @@ -572,12 +628,21 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, case ripRel32Minus1: *loc32 = ref.addend() - 1; return; + case ripRel32Minus1Anon: + *loc32 = (targetAddress - (fixupAddress + 5)) + ref.addend(); + return; case ripRel32Minus2: *loc32 = ref.addend() - 2; return; + case ripRel32Minus2Anon: + *loc32 = (targetAddress - (fixupAddress + 6)) + ref.addend(); + return; case ripRel32Minus4: *loc32 = ref.addend() - 4; return; + case ripRel32Minus4Anon: + *loc32 = (targetAddress - (fixupAddress + 8)) + ref.addend(); + return; case delta32: *loc32 = ref.addend() + inAtomAddress - fixupAddress; return; @@ -638,7 +703,7 @@ void ArchHandler_x86_64::appendSectionRelocations( return; case ripRel32Anon: appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, - X86_64_RELOC_SIGNED | rPcRel | rLength4 ); + X86_64_RELOC_SIGNED | rPcRel | rLength4 ); return; case ripRel32Got: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, @@ -648,6 +713,11 @@ void ArchHandler_x86_64::appendSectionRelocations( appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4 ); return; + case ripRel32Tlv: + appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, + X86_64_RELOC_TLV | rPcRel | rExtern | rLength4 ); + return; + case tlvInitSectionOffset: case pointer64: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_UNSIGNED | rExtern | rLength8); @@ -660,14 +730,26 @@ void ArchHandler_x86_64::appendSectionRelocations( appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4 ); return; + case ripRel32Minus1Anon: + appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, + X86_64_RELOC_SIGNED_1 | rPcRel | rLength4 ); + return; case ripRel32Minus2: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4 ); return; + case ripRel32Minus2Anon: + appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, + X86_64_RELOC_SIGNED_2 | rPcRel | rLength4 ); + return; case ripRel32Minus4: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4 ); return; + case ripRel32Minus4Anon: + appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, + X86_64_RELOC_SIGNED_4 | rPcRel | rLength4 ); + return; case delta32: appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 ); @@ -714,7 +796,6 @@ void ArchHandler_x86_64::appendSectionRelocations( llvm_unreachable("unknown x86_64 Reference Kind"); } - std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86_64() { return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86_64()); } |
