[llvm] cc4ad2c - [JITLink][ELF/x86-64] Add support for GOTOFF64 relocation.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 22 10:40:57 PDT 2021
Author: Lang Hames
Date: 2021-03-22T10:40:50-07:00
New Revision: cc4ad2c540c46bd1e3da065040786769c92b8a13
URL: https://github.com/llvm/llvm-project/commit/cc4ad2c540c46bd1e3da065040786769c92b8a13
DIFF: https://github.com/llvm/llvm-project/commit/cc4ad2c540c46bd1e3da065040786769c92b8a13.diff
LOG: [JITLink][ELF/x86-64] Add support for GOTOFF64 relocation.
Added:
Modified:
llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
index 0a593b2b4a31..d8ed953363e6 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
@@ -37,6 +37,7 @@ enum ELFX86RelocationKind : Edge::Kind {
PCRel32GOTLoad,
PCRel32GOT,
PCRel64GOT,
+ GOTOFF64,
GOT64,
PCRel32TLV,
Delta32,
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index eb38313b4280..17c537eea6b5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -29,6 +29,9 @@ using namespace llvm::jitlink::ELF_x86_64_Edges;
namespace {
+constexpr StringRef ELFGOTSectionName = "$__GOT";
+constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
+
class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
: public PerGraphGOTAndPLTStubsBuilder<
PerGraphGOTAndPLTStubsBuilder_ELF_x86_64> {
@@ -40,6 +43,13 @@ class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
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;
}
@@ -100,13 +110,13 @@ class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
}
private:
- Section &getGOTSection() {
+ Section &getGOTSection() const {
if (!GOTSection)
- GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
+ GOTSection = &G.createSection(ELFGOTSectionName, sys::Memory::MF_READ);
return *GOTSection;
}
- Section &getStubsSection() {
+ Section &getStubsSection() const {
if (!StubsSection) {
auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
sys::Memory::MF_READ | sys::Memory::MF_EXEC);
@@ -125,13 +135,10 @@ class PerGraphGOTAndPLTStubsBuilder_ELF_x86_64
sizeof(StubContent));
}
- Section *GOTSection = nullptr;
- Section *StubsSection = nullptr;
+ mutable Section *GOTSection = nullptr;
+ mutable Section *StubsSection = nullptr;
};
-constexpr StringRef ELFGOTSectionName = "$__GOT";
-constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
-
const char *const DwarfSectionNames[] = {
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
ELF_NAME,
@@ -270,6 +277,8 @@ class ELFLinkGraphBuilder_x86_64 {
return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel64GOT;
case ELF::R_X86_64_GOT64:
return ELF_x86_64_Edges::ELFX86RelocationKind::GOT64;
+ case ELF::R_X86_64_GOTOFF64:
+ return ELF_x86_64_Edges::ELFX86RelocationKind::GOTOFF64;
case ELF::R_X86_64_PLT32:
return ELF_x86_64_Edges::ELFX86RelocationKind::Branch32;
}
@@ -726,13 +735,11 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
Symbol *GOTSymbol = nullptr;
Error getOrCreateGOTSymbol(LinkGraph &G) {
- Section *GOTSection = nullptr;
-
auto DefineExternalGOTSymbolIfPresent =
createDefineExternalSectionStartAndEndSymbolsPass(
[&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
if (Sym.getName() == ELFGOTSymbolName)
- if ((GOTSection = G.findSectionByName(ELFGOTSectionName))) {
+ if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) {
GOTSymbol = &Sym;
return {*GOTSection, true};
}
@@ -744,8 +751,14 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
if (auto Err = DefineExternalGOTSymbolIfPresent(G))
return Err;
+ // If we succeeded then we're done.
+ if (GOTSymbol)
+ return Error::success();
+
+ // 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 (GOTSection && !GOTSymbol) {
+ if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) {
// Check for an existing defined symbol.
for (auto *Sym : GOTSection->symbols())
@@ -822,7 +835,13 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
*(little64_t *)FixupPtr = Value;
break;
}
- case ELFX86RelocationKind::GOT64: {
+ 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();
diff --git a/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
index 50f073beb662..147f2b48bbb7 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s
@@ -111,6 +111,16 @@ test_rex_gotpcrelx:
.size test_rex_gotpcrelx, .-test_rex_gotpcrelx
+# Test GOTOFF64 handling.
+# jitlink-check: decode_operand(test_gotoff64, 1) = named_func - _GLOBAL_OFFSET_TABLE_
+ .globl test_gotoff64
+ .p2align 4, 0x90
+ .type test_gotoff64, at function
+test_gotoff64:
+ movabsq $named_func at GOTOFF, %rax
+
+ .size test_gotoff64, .-test_gotoff64
+
# Test that relocations to anonymous constant pool entries work.
.globl test_anchor_LCPI
.p2align 4, 0x90
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index efa39b02b325..3f222af3222d 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -116,11 +116,15 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
return make_error<StringError>("zero-fill atom in GOT section",
inconvertibleErrorCode());
- if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
- FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(),
- Sym->getAddress()};
- else
- return TS.takeError();
+ // If this is a GOT symbol with size (i.e. not the GOT start symbol)
+ // then add it to the GOT entry info table.
+ if (Sym->getSize() != 0) {
+ if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
+ FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(),
+ Sym->getAddress()};
+ else
+ return TS.takeError();
+ }
SectionContainsContent = true;
} else if (isStubsSection) {
if (Sym->isSymbolZeroFill())
More information about the llvm-commits
mailing list