aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
diff options
context:
space:
mode:
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.cpp575
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));
}