84 changes: 71 additions & 13 deletions llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
using namespace llvm;
using namespace llvm::jitlink;

namespace llvm {
namespace jitlink {
namespace llvm::jitlink {

class ELFJITLinker_i386 : public JITLinker<ELFJITLinker_i386> {
friend class JITLinker<ELFJITLinker_i386>;
Expand All @@ -35,15 +34,7 @@ class ELFJITLinker_i386 : public JITLinker<ELFJITLinker_i386> {

private:
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
using namespace i386;
using namespace llvm::support;

switch (E.getKind()) {
case i386::None: {
break;
}
}
return Error::success();
return i386::applyFixup(G, B, E);
}
};

Expand All @@ -55,6 +46,16 @@ class ELFLinkGraphBuilder_i386 : public ELFLinkGraphBuilder<ELFT> {
switch (Type) {
case ELF::R_386_NONE:
return EdgeKind_i386::None;
case ELF::R_386_32:
return EdgeKind_i386::Pointer32;
case ELF::R_386_PC32:
return EdgeKind_i386::PCRel32;
case ELF::R_386_16:
return EdgeKind_i386::Pointer16;
case ELF::R_386_PC16:
return EdgeKind_i386::PCRel16;
case ELF::R_386_GOTPC:
return EdgeKind_i386::Delta32FromGOT;
}

return make_error<JITLinkError>("Unsupported i386 relocation:" +
Expand All @@ -63,6 +64,64 @@ class ELFLinkGraphBuilder_i386 : public ELFLinkGraphBuilder<ELFT> {

Error addRelocations() override {
LLVM_DEBUG(dbgs() << "Adding relocations\n");
using Base = ELFLinkGraphBuilder<ELFT>;
using Self = ELFLinkGraphBuilder_i386;

for (const auto &RelSect : Base::Sections) {
// Validate the section to read relocation entries from.
if (RelSect.sh_type == ELF::SHT_RELA)
return make_error<StringError>(
"No SHT_RELA in valid i386 ELF object files",
inconvertibleErrorCode());

if (Error Err = Base::forEachRelRelocation(RelSect, this,
&Self::addSingleRelocation))
return Err;
}

return Error::success();
}

Error addSingleRelocation(const typename ELFT::Rel &Rel,
const typename ELFT::Shdr &FixupSection,
Block &BlockToFix) {
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());

Expected<i386::EdgeKind_i386> Kind = getRelocationKind(Rel.getType(false));
if (!Kind)
return Kind.takeError();

// TODO: To be removed when GOT relative relocations are supported.
if (*Kind == i386::EdgeKind_i386::Delta32FromGOT)
return Error::success();

int64_t Addend = 0;

auto FixupAddress = orc::ExecutorAddr(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, i386::getEdgeKindName(*Kind));
dbgs() << "\n";
});

BlockToFix.addEdge(std::move(GE));

return Error::success();
}

Expand Down Expand Up @@ -110,5 +169,4 @@ void link_ELF_i386(std::unique_ptr<LinkGraph> G,
ELFJITLinker_i386::link(std::move(Ctx), std::move(G), std::move(Config));
}

} // namespace jitlink
} // namespace llvm
} // namespace llvm::jitlink
4 changes: 2 additions & 2 deletions llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,8 @@ class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
using Base = ELFLinkGraphBuilder<ELFT>;
using Self = ELFLinkGraphBuilder_riscv<ELFT>;
for (const auto &RelSect : Base::Sections)
if (Error Err = Base::forEachRelocation(RelSect, this,
&Self::addSingleRelocation))
if (Error Err = Base::forEachRelaRelocation(RelSect, this,
&Self::addSingleRelocation))
return Err;

return Error::success();
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
"No SHT_REL in valid x64 ELF object files",
inconvertibleErrorCode());

if (Error Err = Base::forEachRelocation(RelSect, this,
&Self::addSingleRelocation))
if (Error Err = Base::forEachRelaRelocation(RelSect, this,
&Self::addSingleRelocation))
return Err;
}

Expand Down
17 changes: 11 additions & 6 deletions llvm/lib/ExecutionEngine/JITLink/i386.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,22 @@

#define DEBUG_TYPE "jitlink"

namespace llvm {
namespace jitlink {
namespace i386 {
namespace llvm::jitlink::i386 {

const char *getEdgeKindName(Edge::Kind K) {
switch (K) {
case None:
return "None";
case Pointer32:
return "Pointer32";
case PCRel32:
return "PCRel32";
case Pointer16:
return "Pointer16";
case PCRel16:
return "PCRel16";
}
return getGenericEdgeKindName(K);
}
} // namespace i386
} // namespace jitlink
} // namespace llvm

} // namespace llvm::jitlink::i386
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# RUN: llvm-mc -triple=i386-unknown-linux-gnu -filetype=obj -o %t.o %s
# RUN: llvm-jitlink -noexec %t.o

.text
.globl main
.p2align 4
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
pushl %eax
movl $0, -4(%ebp)
movl a, %eax
addl $4, %esp
popl %ebp
retl

.size main, .-main

.data
.p2align 2
.type a,@object
a:
.long 42
.size a, 4
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# RUN: llvm-mc -triple=i386-unknown-linux-gnu -filetype=obj -o %t.o %s
# RUN: llvm-jitlink -noexec %t.o

.text
.section .text.main
.globl main
.p2align 4
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $0, -4(%ebp)
calll foo
addl $8, %esp
popl %ebp
retl

.size main, .-main

.section .text.foo
.p2align 4
.type foo,@function
foo:
pushl %ebp
movl %esp, %ebp
movl $42, %eax
popl %ebp
retl

.size foo, .-foo
4 changes: 2 additions & 2 deletions llvm/test/ExecutionEngine/JITLink/i386/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
if not 'i386' in config.root.targets:
config.unsupported = True
if not 'X86' in config.root.targets:
config.unsupported = True