[llvm] 3f0841f - [jitlink] R_X86_64_PC32 support for the elf x86 jitlinker
Jared Wyles via llvm-commits
llvm-commits at lists.llvm.org
Fri May 29 17:53:33 PDT 2020
Author: Jared Wyles
Date: 2020-05-30T10:53:18+10:00
New Revision: 3f0841f6d0a0eb86a1c36cc0c76931ae9d7bc77a
URL: https://github.com/llvm/llvm-project/commit/3f0841f6d0a0eb86a1c36cc0c76931ae9d7bc77a
DIFF: https://github.com/llvm/llvm-project/commit/3f0841f6d0a0eb86a1c36cc0c76931ae9d7bc77a.diff
LOG: [jitlink] R_X86_64_PC32 support for the elf x86 jitlinker
Summary:
Adding in our first relocation type, and all the required plumbing to support the rest in following patches
Differential Revision: https://reviews.llvm.org/D80613
Reviewer: lhames
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_relocations.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
index ee43c356aebe..7860088f3569 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h
@@ -19,36 +19,33 @@ namespace llvm {
namespace jitlink {
namespace ELF_x86_64_Edges {
-
enum ELFX86RelocationKind : Edge::Kind {
- R_AMD64_NONE = Edge::FirstRelocation,
- R_AMD64_64,
- R_AMD64_PC32,
- R_AMD64_GOT32,
- R_AMD64_PLT32,
- R_AMD64_COPY,
- R_AMD64_GLOB_DAT,
- R_AMD64_JUMP_SLOT,
- R_AMD64_RELATIVE,
- R_AMD64_GOTPCREL,
- R_AMD64_32,
- R_AMD64_32S,
- R_AMD64_16,
- R_AMD64_PC16,
- R_AMD64_8,
- R_AMD64_PC8,
- R_AMD64_PC64,
- R_AMD64_GOTOFF64,
- R_AMD64_GOTPC32,
- R_AMD64_SIZE32,
- R_AMD64_SIZE64
+ Branch32 = Edge::FirstRelocation,
+ Branch32ToStub,
+ Pointer32,
+ Pointer64,
+ Pointer64Anon,
+ PCRel32,
+ PCRel32Minus1,
+ PCRel32Minus2,
+ PCRel32Minus4,
+ PCRel32Anon,
+ PCRel32Minus1Anon,
+ PCRel32Minus2Anon,
+ PCRel32Minus4Anon,
+ PCRel32GOTLoad,
+ PCRel32GOT,
+ PCRel32TLV,
+ Delta32,
+ Delta64,
+ NegDelta32,
+ NegDelta64,
};
} // end namespace ELF_x86_64_Edges
/// jit-link the given object buffer, which must be a ELF x86-64 object file.
void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx);
-StringRef getELFX86RelocationKindName(Edge::Kind R);
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index a7118eb9b563..505f03590b6b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -24,12 +24,19 @@ static const char *CommonSectionName = "__common";
namespace llvm {
namespace jitlink {
+
// This should become a template as the ELFFile is so a lot of this could become
// generic
class ELFLinkGraphBuilder_x86_64 {
private:
Section *CommonSection = nullptr;
+ // TODO hack to get this working
+ // Find a better way
+ using SymbolTable = object::ELFFile<object::ELF64LE>::Elf_Shdr;
+ // For now we just assume
+ std::map<int32_t, Symbol *> JITSymbolTable;
+
Section &getCommonSection() {
if (!CommonSection) {
auto Prot = static_cast<sys::Memory::ProtectionFlags>(
@@ -39,10 +46,21 @@ class ELFLinkGraphBuilder_x86_64 {
return *CommonSection;
}
+ static Expected<ELF_x86_64_Edges::ELFX86RelocationKind>
+ getRelocationKind(const uint32_t Type) {
+ switch (Type) {
+ case ELF::R_X86_64_PC32:
+ return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32;
+ }
+ return make_error<JITLinkError>("Unsupported x86-64 relocation:" +
+ formatv("{0:d}", Type));
+ }
+
std::unique_ptr<LinkGraph> G;
// This could be a template
const object::ELFFile<object::ELF64LE> &Obj;
object::ELFFile<object::ELF64LE>::Elf_Shdr_Range sections;
+ SymbolTable SymTab;
bool isRelocatable() { return Obj.getHeader()->e_type == llvm::ELF::ET_REL; }
@@ -88,11 +106,11 @@ class ELFLinkGraphBuilder_x86_64 {
// FIXME: Read size.
(void)Size;
- if (auto NameOrErr = SymRef.getName(*StringTable)) {
+ if (auto NameOrErr = SymRef.getName(*StringTable))
Name = *NameOrErr;
- } else {
+ else
return NameOrErr.takeError();
- }
+
LLVM_DEBUG({
dbgs() << " ";
if (!Name)
@@ -157,12 +175,93 @@ class ELFLinkGraphBuilder_x86_64 {
// Do this here because we have it, but move it into graphify later
G->createContentBlock(section, StringRef(Data, Size), Address,
Alignment, 0);
+ if (SecRef.sh_type == ELF::SHT_SYMTAB)
+ // TODO: Dynamic?
+ SymTab = SecRef;
}
}
return Error::success();
}
+ Error addRelocations() {
+ 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();
+ // Deal with .eh_frame later
+ if (*RelSectName == StringRef(".rela.eh_frame"))
+ continue;
+
+ auto UpdateSection = Obj.getSection(SecRef.sh_info);
+ if (!UpdateSection)
+ return UpdateSection.takeError();
+
+ auto UpdateSectionName = Obj.getSectionName(*UpdateSection);
+ if (!UpdateSectionName)
+ return UpdateSectionName.takeError();
+
+ 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 Symbol = Obj.getRelocationSymbol(&Rela, &SymTab);
+ if (!Symbol)
+ return Symbol.takeError();
+
+ auto BlockToFix = *(JITSection->blocks().begin());
+ auto TargetSymbol = JITSymbolTable[(*Symbol)->st_shndx];
+ 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);
+ // TODO a mapping of KIND => type then call getRelocationTypeName4
+ printEdge(dbgs(), *BlockToFix, GE, StringRef(""));
+ dbgs() << "\n";
+ });
+ BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
+ *TargetSymbol, Addend);
+ }
+ }
+ return Error::success();
+ }
+
Error graphifyRegularSymbols() {
// TODO: ELF supports beyond SHN_LORESERVE,
@@ -219,11 +318,10 @@ class ELFLinkGraphBuilder_x86_64 {
if (!Name)
return Name.takeError();
// TODO: weak and hidden
- if (SymRef.isExternal()) {
+ if (SymRef.isExternal())
bindings = {Linkage::Strong, Scope::Default};
- } else {
+ else
bindings = {Linkage::Strong, Scope::Local};
- }
if (SymRef.isDefined() &&
(Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT)) {
@@ -247,9 +345,10 @@ class ELFLinkGraphBuilder_x86_64 {
auto B = *bs.begin();
LLVM_DEBUG({ dbgs() << " " << *Name << ": "; });
- G->addDefinedSymbol(*B, SymRef.getValue(), *Name, SymRef.st_size,
- bindings.first, bindings.second,
- SymRef.getType() == ELF::STT_FUNC, false);
+ auto &S = G->addDefinedSymbol(
+ *B, SymRef.getValue(), *Name, SymRef.st_size, bindings.first,
+ bindings.second, SymRef.getType() == ELF::STT_FUNC, false);
+ JITSymbolTable[SymRef.st_shndx] = &S;
}
//TODO: The following has to be implmented.
// leaving commented out to save time for future patchs
@@ -298,6 +397,9 @@ class ELFLinkGraphBuilder_x86_64 {
if (auto Err = graphifyRegularSymbols())
return std::move(Err);
+ if (auto Err = addRelocations())
+ return std::move(Err);
+
return std::move(G);
}
};
@@ -311,9 +413,7 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
: JITLinker(std::move(Ctx), std::move(PassConfig)) {}
private:
- StringRef getEdgeKindName(Edge::Kind R) const override {
- return getELFX86RelocationKindName(R);
- }
+ StringRef getEdgeKindName(Edge::Kind R) const override { return StringRef(); }
Expected<std::unique_ptr<LinkGraph>>
buildGraph(MemoryBufferRef ObjBuffer) override {
@@ -329,7 +429,17 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
}
Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
- //TODO: add relocation handling
+ using namespace ELF_x86_64_Edges;
+ char *FixupPtr = BlockWorkingMem + E.getOffset();
+ JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
+ switch (E.getKind()) {
+
+ case ELFX86RelocationKind::PCRel32:
+ int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+ // verify
+ *(support::little32_t *)FixupPtr = Value;
+ break;
+ }
return Error::success();
}
};
@@ -349,30 +459,5 @@ void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
ELFJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
}
-
-StringRef getELFX86RelocationKindName(Edge::Kind R) {
- // case R_AMD64_NONE:
- // return "None";
- // case R_AMD64_PC32:
- // case R_AMD64_GOT32:
- // case R_AMD64_PLT32,
- // R_AMD64_COPY,
- // R_AMD64_GLOB_DAT,
- // R_AMD64_JUMP_SLOT,
- // R_AMD64_RELATIVE,
- // R_AMD64_GOTPCREL,
- // R_AMD64_32,
- // R_AMD64_32S,
- // R_AMD64_16,
- // R_AMD64_PC16,
- // R_AMD64_8,
- // R_AMD64_PC8,
- // R_AMD64_PC64,
- // R_AMD64_GOTOFF64,
- // R_AMD64_GOTPC32,
- // R_AMD64_SIZE32,
- // R_AMD64_SIZE64
- return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
-}
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_relocations.s b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_relocations.s
index 12186e4f5433..20b26b1826ba 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_relocations.s
@@ -1,20 +1,38 @@
# RUN: rm -rf %t && mkdir -p %t
# RUN: llvm-mc -triple=x86_64-unknown-linux -filetype=obj -o %t/elf_reloc.o %s
-# RUN: llvm-jitlink -noexec %t/elf_reloc.o
+# RUN: llvm-jitlink -noexec -check %s %t/elf_reloc.o
#
# Test standard ELF relocations.
.text
.file "testcase.c"
+
+# Empty main entry point.
.globl main
.p2align 4, 0x90
.type main, at function
main:
- movl $42, %eax
retq
.Lfunc_end0:
.size main, .Lfunc_end0-main
+# Test PCRel32 / R_X86_64_PC32 handling.
+# jitlink-check: decode_operand(test_pcrel32, 4) = named_data - next_pc(test_pcrel32)
+ .globl test_pcrel32
+ .p2align 4, 0x90
+ .type test_pcrel32, at function
+test_pcrel32:
+ movl named_data(%rip), %eax
+.Ltest_pcrel32_end:
+ .size test_pcrel32, .Ltest_pcrel32_end-test_pcrel32
+
+ .type named_data, at object
+ .data
+ .p2align 2
+named_data:
+ .long 42
+ .size named_data, 4
+
.ident "clang version 10.0.0-4ubuntu1 "
.section ".note.GNU-stack","", at progbits
- .addrsig
\ No newline at end of file
+ .addrsig
More information about the llvm-commits
mailing list