diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp | 575 |
1 files changed, 194 insertions, 381 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index a5aed6d25200..3ea9ffee6554 100644 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -12,6 +12,7 @@ #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" +#include "llvm/ExecutionEngine/JITLink/TableManager.h" #include "llvm/ExecutionEngine/JITLink/x86_64.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Endian.h" @@ -20,7 +21,6 @@ #include "EHFrameSupportImpl.h" #include "ELFLinkGraphBuilder.h" #include "JITLinkGeneric.h" -#include "PerGraphGOTAndPLTStubsBuilder.h" #define DEBUG_TYPE "jitlink" @@ -30,196 +30,82 @@ using namespace llvm::jitlink::ELF_x86_64_Edges; namespace { -constexpr StringRef ELFGOTSectionName = "$__GOT"; constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_"; +constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO"; -class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64 - : public PerGraphGOTAndPLTStubsBuilder< - PerGraphGOTAndPLTStubsBuilder_ELF_x86_64> { +class TLSInfoTableManager_ELF_x86_64 + : public TableManager<TLSInfoTableManager_ELF_x86_64> { public: - static const uint8_t NullGOTEntryContent[8]; - static const uint8_t StubContent[6]; - - using PerGraphGOTAndPLTStubsBuilder< - PerGraphGOTAndPLTStubsBuilder_ELF_x86_64>::PerGraphGOTAndPLTStubsBuilder; - - bool isGOTEdgeToFix(Edge &E) const { - if (E.getKind() == GOTOFF64) { - // We need to make sure that the GOT section exists, but don't otherwise - // need to fix up this edge. - getGOTSection(); - return false; - } - - return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad || - E.getKind() == PCRel64GOT || E.getKind() == GOT64; - } + static const uint8_t TLSInfoEntryContent[16]; - Symbol &createGOTEntry(Symbol &Target) { - auto &GOTEntryBlock = G.createContentBlock( - getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0); - GOTEntryBlock.addEdge(Pointer64, 0, Target, 0); - return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false); - } + static StringRef getSectionName() { return ELFTLSInfoSectionName; } - void fixGOTEdge(Edge &E, Symbol &GOTEntry) { - // If this is a PCRel32GOT/PCRel64GOT then change it to an ordinary - // PCRel32/PCRel64. If it is a PCRel32GOTLoad then leave it as-is for now: - // We will use the kind to check for GOT optimization opportunities in the - // optimizeMachO_x86_64_GOTAndStubs pass below. - // If it's a GOT64 leave it as is. - switch (E.getKind()) { - case PCRel32GOT: - E.setKind(PCRel32); - break; - case PCRel64GOT: - E.setKind(PCRel64); - break; - case GOT64: - break; - case PCRel32GOTLoad: - break; - default: - llvm_unreachable("Unexpected GOT edge kind"); + bool visitEdge(LinkGraph &G, Block *B, Edge &E) { + if (E.getKind() == x86_64::RequestTLSDescInGOTAndTransformToDelta32) { + LLVM_DEBUG({ + dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " + << formatv("{0:x}", B->getFixupAddress(E)) << " (" + << formatv("{0:x}", B->getAddress()) << " + " + << formatv("{0:x}", E.getOffset()) << ")\n"; + }); + E.setKind(x86_64::Delta32); + E.setTarget(getEntryForTarget(G, E.getTarget())); + return true; } - - E.setTarget(GOTEntry); - // Leave the edge addend as-is. + return false; } - bool isExternalBranchEdge(Edge &E) { - return E.getKind() == Branch32 && !E.getTarget().isDefined(); - } - - Symbol &createPLTStub(Symbol &Target) { - auto &StubContentBlock = - G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0); - // Re-use GOT entries for stub targets. - auto &GOTEntrySymbol = getGOTEntry(Target); - StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, -4); - return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false); - } - - void fixPLTEdge(Edge &E, Symbol &Stub) { - assert(E.getKind() == Branch32 && "Not a Branch32 edge?"); - - // Set the edge kind to Branch32ToStub. We will use this to check for stub - // optimization opportunities in the optimize ELF_x86_64_GOTAndStubs pass - // below. - E.setKind(Branch32ToStub); - E.setTarget(Stub); + Symbol &createEntry(LinkGraph &G, Symbol &Target) { + // the TLS Info entry's key value will be written by the fixTLVSectionByName + // pass, so create mutable content. + auto &TLSInfoEntry = G.createMutableContentBlock( + getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 0, 8, + 0); + TLSInfoEntry.addEdge(x86_64::Pointer64, 8, Target, 0); + return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false); } private: - Section &getGOTSection() const { - if (!GOTSection) - GOTSection = &G.createSection(ELFGOTSectionName, sys::Memory::MF_READ); - return *GOTSection; - } - - Section &getStubsSection() const { - if (!StubsSection) { - auto StubsProt = static_cast<sys::Memory::ProtectionFlags>( - sys::Memory::MF_READ | sys::Memory::MF_EXEC); - StubsSection = &G.createSection("$__STUBS", StubsProt); - } - return *StubsSection; - } - - ArrayRef<char> getGOTEntryBlockContent() { - return {reinterpret_cast<const char *>(NullGOTEntryContent), - sizeof(NullGOTEntryContent)}; + Section &getTLSInfoSection(LinkGraph &G) { + if (!TLSInfoTable) + TLSInfoTable = &G.createSection(ELFTLSInfoSectionName, MemProt::Read); + return *TLSInfoTable; } - ArrayRef<char> getStubBlockContent() { - return {reinterpret_cast<const char *>(StubContent), sizeof(StubContent)}; + ArrayRef<char> getTLSInfoEntryContent() const { + return {reinterpret_cast<const char *>(TLSInfoEntryContent), + sizeof(TLSInfoEntryContent)}; } - mutable Section *GOTSection = nullptr; - mutable Section *StubsSection = nullptr; + Section *TLSInfoTable = nullptr; }; -} // namespace +const uint8_t TLSInfoTableManager_ELF_x86_64::TLSInfoEntryContent[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ +}; -const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::NullGOTEntryContent[8] = - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const uint8_t PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::StubContent[6] = { - 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00}; - -static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) { - LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n"); - - for (auto *B : G.blocks()) - for (auto &E : B->edges()) - if (E.getKind() == PCRel32GOTLoad) { - // Replace GOT load with LEA only for MOVQ instructions. - constexpr uint8_t MOVQRIPRel[] = {0x48, 0x8b}; - if (E.getOffset() < 3 || - strncmp(B->getContent().data() + E.getOffset() - 3, - reinterpret_cast<const char *>(MOVQRIPRel), 2) != 0) - continue; - - auto &GOTBlock = E.getTarget().getBlock(); - assert(GOTBlock.getSize() == G.getPointerSize() && - "GOT entry block should be pointer sized"); - assert(GOTBlock.edges_size() == 1 && - "GOT entry should only have one outgoing edge"); - - auto &GOTTarget = GOTBlock.edges().begin()->getTarget(); - JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset(); - JITTargetAddress TargetAddr = GOTTarget.getAddress(); - - int64_t Displacement = TargetAddr - EdgeAddr + 4; - if (Displacement >= std::numeric_limits<int32_t>::min() && - Displacement <= std::numeric_limits<int32_t>::max()) { - // Change the edge kind as we don't go through GOT anymore. This is - // for formal correctness only. Technically, the two relocation kinds - // are resolved the same way. - E.setKind(PCRel32); - E.setTarget(GOTTarget); - auto *BlockData = reinterpret_cast<uint8_t *>( - const_cast<char *>(B->getContent().data())); - BlockData[E.getOffset() - 2] = 0x8d; - LLVM_DEBUG({ - dbgs() << " Replaced GOT load wih LEA:\n "; - printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind())); - dbgs() << "\n"; - }); - } - } else if (E.getKind() == Branch32ToStub) { - auto &StubBlock = E.getTarget().getBlock(); - assert( - StubBlock.getSize() == - sizeof(PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::StubContent) && - "Stub block should be stub sized"); - assert(StubBlock.edges_size() == 1 && - "Stub block should only have one outgoing edge"); - - auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock(); - assert(GOTBlock.getSize() == G.getPointerSize() && - "GOT block should be pointer sized"); - assert(GOTBlock.edges_size() == 1 && - "GOT block should only have one outgoing edge"); - - auto &GOTTarget = GOTBlock.edges().begin()->getTarget(); - JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset(); - JITTargetAddress TargetAddr = GOTTarget.getAddress(); - - int64_t Displacement = TargetAddr - EdgeAddr + 4; - if (Displacement >= std::numeric_limits<int32_t>::min() && - Displacement <= std::numeric_limits<int32_t>::max()) { - E.setKind(Branch32); - E.setTarget(GOTTarget); - LLVM_DEBUG({ - dbgs() << " Replaced stub branch with direct branch:\n "; - printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind())); - dbgs() << "\n"; - }); - } - } +Error buildTables_ELF_x86_64(LinkGraph &G) { + LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); + x86_64::GOTTableManager GOT; + x86_64::PLTTableManager PLT(GOT); + TLSInfoTableManager_ELF_x86_64 TLSInfo; + visitExistingEdges(G, GOT, PLT, TLSInfo); return Error::success(); } +} // namespace + +static const char *getELFX86_64RelocName(uint32_t Type) { + switch (Type) { +#define ELF_RELOC(Name, Number) \ + case Number: \ + return #Name; +#include "llvm/BinaryFormat/ELFRelocs/x86_64.def" +#undef ELF_RELOC + } + return "Unrecognized ELF/x86-64 relocation type"; +} namespace llvm { namespace jitlink { @@ -228,10 +114,13 @@ namespace jitlink { // generic class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> { private: + using ELFT = object::ELF64LE; static Expected<ELF_x86_64_Edges::ELFX86RelocationKind> getRelocationKind(const uint32_t Type) { switch (Type) { + case ELF::R_X86_64_32S: + return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer32Signed; case ELF::R_X86_64_PC32: return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32; case ELF::R_X86_64_PC64: @@ -240,9 +129,11 @@ private: case ELF::R_X86_64_64: return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer64; case ELF::R_X86_64_GOTPCREL: + return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoad; case ELF::R_X86_64_GOTPCRELX: + return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoadRelaxable; case ELF::R_X86_64_REX_GOTPCRELX: - return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoad; + return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32REXGOTLoadRelaxable; case ELF::R_X86_64_GOTPCREL64: return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel64GOT; case ELF::R_X86_64_GOT64: @@ -251,109 +142,121 @@ private: return ELF_x86_64_Edges::ELFX86RelocationKind::GOTOFF64; case ELF::R_X86_64_PLT32: return ELF_x86_64_Edges::ELFX86RelocationKind::Branch32; + case ELF::R_X86_64_TLSGD: + return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32TLV; } - return make_error<JITLinkError>("Unsupported x86-64 relocation:" + - formatv("{0:d}", Type)); + return make_error<JITLinkError>("Unsupported x86-64 relocation type " + + formatv("{0:d}: ", Type) + + getELFX86_64RelocName(Type)); } Error addRelocations() override { - LLVM_DEBUG(dbgs() << "Adding relocations\n"); - // TODO a partern is forming of iterate some sections but only give me - // ones I am interested, i should abstract that concept some where - for (auto &SecRef : Sections) { - if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL) - continue; - // TODO can the elf obj file do this for me? - if (SecRef.sh_type == ELF::SHT_REL) - return make_error<llvm::StringError>("Shouldn't have REL in x64", - llvm::inconvertibleErrorCode()); - - auto RelSectName = Obj.getSectionName(SecRef); - if (!RelSectName) - return RelSectName.takeError(); + LLVM_DEBUG(dbgs() << "Processing relocations:\n"); + + using Base = ELFLinkGraphBuilder<ELFT>; + using Self = ELFLinkGraphBuilder_x86_64; + for (const auto &RelSect : Base::Sections) { + // Validate the section to read relocation entries from. + if (RelSect.sh_type == ELF::SHT_REL) + return make_error<StringError>( + "No SHT_REL in valid x64 ELF object files", + inconvertibleErrorCode()); + + if (Error Err = Base::forEachRelocation(RelSect, this, + &Self::addSingleRelocation)) + return Err; + } - LLVM_DEBUG({ - dbgs() << "Adding relocations from section " << *RelSectName << "\n"; - }); + return Error::success(); + } - auto UpdateSection = Obj.getSection(SecRef.sh_info); - if (!UpdateSection) - return UpdateSection.takeError(); - - auto UpdateSectionName = Obj.getSectionName(**UpdateSection); - if (!UpdateSectionName) - return UpdateSectionName.takeError(); - - // Don't process relocations for debug sections. - if (isDwarfSection(*UpdateSectionName)) { - LLVM_DEBUG({ - dbgs() << " Target is dwarf section " << *UpdateSectionName - << ". Skipping.\n"; - }); - continue; - } else - LLVM_DEBUG({ - dbgs() << " For target section " << *UpdateSectionName << "\n"; - }); - - auto JITSection = G->findSectionByName(*UpdateSectionName); - if (!JITSection) - return make_error<llvm::StringError>( - "Refencing a a section that wasn't added to graph" + - *UpdateSectionName, - llvm::inconvertibleErrorCode()); - - auto Relocations = Obj.relas(SecRef); - if (!Relocations) - return Relocations.takeError(); - - for (const auto &Rela : *Relocations) { - auto Type = Rela.getType(false); - - LLVM_DEBUG({ - dbgs() << "Relocation Type: " << Type << "\n" - << "Name: " << Obj.getRelocationTypeName(Type) << "\n"; - }); - auto SymbolIndex = Rela.getSymbol(false); - auto Symbol = Obj.getRelocationSymbol(Rela, SymTabSec); - if (!Symbol) - return Symbol.takeError(); - - auto BlockToFix = *(JITSection->blocks().begin()); - auto *TargetSymbol = getGraphSymbol(SymbolIndex); - - if (!TargetSymbol) { - return make_error<llvm::StringError>( - "Could not find symbol at given index, did you add it to " - "JITSymbolTable? index: " + - std::to_string(SymbolIndex) + - ", shndx: " + std::to_string((*Symbol)->st_shndx) + - " Size of table: " + std::to_string(GraphSymbols.size()), - llvm::inconvertibleErrorCode()); - } - uint64_t Addend = Rela.r_addend; - JITTargetAddress FixupAddress = - (*UpdateSection)->sh_addr + Rela.r_offset; - - LLVM_DEBUG({ - dbgs() << "Processing relocation at " - << format("0x%016" PRIx64, FixupAddress) << "\n"; - }); - auto Kind = getRelocationKind(Type); - if (!Kind) - return Kind.takeError(); - - LLVM_DEBUG({ - Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol, - Addend); - printEdge(dbgs(), *BlockToFix, GE, - getELFX86RelocationKindName(*Kind)); - dbgs() << "\n"; - }); - BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(), - *TargetSymbol, Addend); - } + Error addSingleRelocation(const typename ELFT::Rela &Rel, + const typename ELFT::Shdr &FixupSection, + Section &GraphSection) { + using Base = ELFLinkGraphBuilder<ELFT>; + + uint32_t SymbolIndex = Rel.getSymbol(false); + auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); + if (!ObjSymbol) + return ObjSymbol.takeError(); + + Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); + if (!GraphSymbol) + return make_error<StringError>( + formatv("Could not find symbol at given index, did you add it to " + "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", + SymbolIndex, (*ObjSymbol)->st_shndx, + Base::GraphSymbols.size()), + inconvertibleErrorCode()); + + // Validate the relocation kind. + auto ELFRelocKind = getRelocationKind(Rel.getType(false)); + if (!ELFRelocKind) + return ELFRelocKind.takeError(); + + int64_t Addend = Rel.r_addend; + Edge::Kind Kind = Edge::Invalid; + switch (*ELFRelocKind) { + case PCRel32: + Kind = x86_64::Delta32; + break; + case Delta64: + Kind = x86_64::Delta64; + break; + case Pointer32Signed: + Kind = x86_64::Pointer32Signed; + break; + case Pointer64: + Kind = x86_64::Pointer64; + break; + case PCRel32GOTLoad: { + Kind = x86_64::RequestGOTAndTransformToDelta32; + break; + } + case PCRel32REXGOTLoadRelaxable: { + Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable; + Addend = 0; + break; + } + case PCRel32TLV: { + Kind = x86_64::RequestTLSDescInGOTAndTransformToDelta32; + break; + } + case PCRel32GOTLoadRelaxable: { + Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable; + Addend = 0; + break; + } + case PCRel64GOT: { + Kind = x86_64::RequestGOTAndTransformToDelta64; + break; + } + case GOT64: { + Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT; + break; + } + case GOTOFF64: { + Kind = x86_64::Delta64FromGOT; + break; + } + case Branch32: { + Kind = x86_64::BranchPCRel32; + Addend = 0; + break; } + } + + Block *BlockToFix = *(GraphSection.blocks().begin()); + JITTargetAddress FixupAddress = FixupSection.sh_addr + Rel.r_offset; + Edge::OffsetT Offset = FixupAddress - BlockToFix->getAddress(); + Edge GE(Kind, Offset, *GraphSymbol, Addend); + LLVM_DEBUG({ + dbgs() << " "; + printEdge(dbgs(), *BlockToFix, GE, getELFX86RelocationKindName(Kind)); + dbgs() << "\n"; + }); + + BlockToFix->addEdge(std::move(GE)); return Error::success(); } @@ -361,7 +264,7 @@ public: ELFLinkGraphBuilder_x86_64(StringRef FileName, const object::ELFFile<object::ELF64LE> &Obj) : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), FileName, - getELFX86RelocationKindName) {} + x86_64::getEdgeKindName) {} }; class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> { @@ -384,7 +287,8 @@ private: createDefineExternalSectionStartAndEndSymbolsPass( [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc { if (Sym.getName() == ELFGOTSymbolName) - if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) { + if (auto *GOTSection = G.findSectionByName( + x86_64::GOTTableManager::getSectionName())) { GOTSymbol = &Sym; return {*GOTSection, true}; } @@ -403,7 +307,8 @@ private: // Otherwise look for a GOT section: If it already has a start symbol we'll // record it, otherwise we'll create our own. // If there's a GOT section but we didn't find an external GOT symbol... - if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) { + if (auto *GOTSection = + G.findSectionByName(x86_64::GOTTableManager::getSectionName())) { // Check for an existing defined symbol. for (auto *Sym : GOTSection->symbols()) @@ -427,81 +332,7 @@ private: } Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { - using namespace ELF_x86_64_Edges; - using namespace llvm::support; - - char *BlockWorkingMem = B.getAlreadyMutableContent().data(); - char *FixupPtr = BlockWorkingMem + E.getOffset(); - JITTargetAddress FixupAddress = B.getAddress() + E.getOffset(); - switch (E.getKind()) { - case ELFX86RelocationKind::Branch32: - case ELFX86RelocationKind::Branch32ToStub: - case ELFX86RelocationKind::PCRel32: - case ELFX86RelocationKind::PCRel32GOTLoad: { - int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; - if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value))) - *(little32_t *)FixupPtr = Value; - else - return makeTargetOutOfRangeError(G, B, E); - break; - } - case ELFX86RelocationKind::PCRel64: { - int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; - *(little64_t *)FixupPtr = Value; - break; - } - case ELFX86RelocationKind::Pointer64: { - int64_t Value = E.getTarget().getAddress() + E.getAddend(); - *(ulittle64_t *)FixupPtr = Value; - break; - } - case ELFX86RelocationKind::Delta32: { - int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; - if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value))) - *(little32_t *)FixupPtr = Value; - else - return makeTargetOutOfRangeError(G, B, E); - break; - } - case ELFX86RelocationKind::Delta64: { - int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; - *(little64_t *)FixupPtr = Value; - break; - } - case ELFX86RelocationKind::NegDelta32: { - int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend(); - if (LLVM_LIKELY(x86_64::isInRangeForImmS32(Value))) - *(little32_t *)FixupPtr = Value; - else - return makeTargetOutOfRangeError(G, B, E); - break; - } - case ELFX86RelocationKind::NegDelta64: { - int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend(); - *(little64_t *)FixupPtr = Value; - break; - } - case ELFX86RelocationKind::GOT64: - case ELFX86RelocationKind::GOTOFF64: { - // GOT64: Offset of GOT entry within GOT. - // GOTOFF64: Offset from GOT base to target. - // The expressions are the same in both cases, but in the GOT64 case the - // edge will have been fixed to point at the GOT entry, and in the - // GOTOFF64 case it will still point at the original target. - assert(GOTSymbol && "No GOT section symbol"); - int64_t Value = - E.getTarget().getAddress() - GOTSymbol->getAddress() + E.getAddend(); - *(little64_t *)FixupPtr = Value; - break; - } - default: - LLVM_DEBUG({ - dbgs() << "Bad edge: " << getELFX86RelocationKindName(E.getKind()) - << "\n"; - }); - llvm_unreachable("Unsupported relocation"); - } - return Error::success(); + return x86_64::applyFixup(G, B, E, GOTSymbol); } }; @@ -547,8 +378,9 @@ void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { Config.PrePrunePasses.push_back(EHFrameSplitter(".eh_frame")); - Config.PrePrunePasses.push_back(EHFrameEdgeFixer( - ".eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32)); + Config.PrePrunePasses.push_back( + EHFrameEdgeFixer(".eh_frame", x86_64::PointerSize, x86_64::Delta64, + x86_64::Delta32, x86_64::NegDelta32)); Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); // Construct a JITLinker and run the link function. @@ -558,9 +390,8 @@ void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, else Config.PrePrunePasses.push_back(markAllSymbolsLive); - // Add an in-place GOT/Stubs pass. - Config.PostPrunePasses.push_back( - PerGraphGOTAndPLTStubsBuilder_ELF_x86_64::asPass); + // Add an in-place GOT/Stubs/TLSInfoEntry build pass. + Config.PostPrunePasses.push_back(buildTables_ELF_x86_64); // Resolve any external section start / end symbols. Config.PostAllocationPasses.push_back( @@ -568,7 +399,7 @@ void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, identifyELFSectionStartAndEndSymbols)); // Add GOT/Stubs optimizer pass. - Config.PreFixupPasses.push_back(optimizeELF_x86_64_GOTAndStubs); + Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses); } if (auto Err = Ctx->modifyPassConfig(*G, Config)) @@ -580,44 +411,26 @@ const char *getELFX86RelocationKindName(Edge::Kind R) { switch (R) { case Branch32: return "Branch32"; - case Branch32ToStub: - return "Branch32ToStub"; - case Pointer32: - return "Pointer32"; + case Pointer32Signed: + return "Pointer32Signed"; case Pointer64: return "Pointer64"; - case Pointer64Anon: - return "Pointer64Anon"; case PCRel32: return "PCRel32"; - case PCRel32Minus1: - return "PCRel32Minus1"; - case PCRel32Minus2: - return "PCRel32Minus2"; - case PCRel32Minus4: - return "PCRel32Minus4"; - case PCRel32Anon: - return "PCRel32Anon"; - case PCRel32Minus1Anon: - return "PCRel32Minus1Anon"; - case PCRel32Minus2Anon: - return "PCRel32Minus2Anon"; - case PCRel32Minus4Anon: - return "PCRel32Minus4Anon"; case PCRel32GOTLoad: return "PCRel32GOTLoad"; - case PCRel32GOT: - return "PCRel32GOT"; - case PCRel32TLV: - return "PCRel32TLV"; - case Delta32: - return "Delta32"; + case PCRel32GOTLoadRelaxable: + return "PCRel32GOTLoadRelaxable"; + case PCRel32REXGOTLoadRelaxable: + return "PCRel32REXGOTLoad"; + case PCRel64GOT: + return "PCRel64GOT"; case Delta64: return "Delta64"; - case NegDelta32: - return "NegDelta32"; - case NegDelta64: - return "NegDelta64"; + case GOT64: + return "GOT64"; + case GOTOFF64: + return "GOTOFF64"; } return getGenericEdgeKindName(static_cast<Edge::Kind>(R)); } |