Skip to content

Commit 83b52b5

Browse files
[JITLink][ELF] Route objects to their matching linker backends based on header info
Distinguish objects by target properties address size, endian and machine architecture. So far we only support x86-64 (ELFCLASS64, ELFDATA2LSB, EM_X86_64). Reviewed By: lhames Differential Revision: https://reviews.llvm.org/D90860
1 parent 2d1b024 commit 83b52b5

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

llvm/lib/ExecutionEngine/JITLink/ELF.cpp

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "llvm/BinaryFormat/ELF.h"
1717
#include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
18+
#include "llvm/Object/ELF.h"
1819
#include "llvm/Support/Endian.h"
1920
#include "llvm/Support/Format.h"
2021
#include "llvm/Support/MemoryBuffer.h"
@@ -27,24 +28,56 @@ using namespace llvm;
2728
namespace llvm {
2829
namespace jitlink {
2930

30-
void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx) {
31+
Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
32+
const char *Data = Buffer.data();
3133

32-
// We don't want to do full ELF validation here. We just verify it is elf'ish.
33-
// Probably should parse into an elf header when we support more than x86 :)
34+
if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
35+
if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
36+
if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
37+
return File->getHeader().e_machine;
38+
} else {
39+
return File.takeError();
40+
}
41+
} else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
42+
if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
43+
return File->getHeader().e_machine;
44+
} else {
45+
return File.takeError();
46+
}
47+
}
48+
}
3449

35-
StringRef Data = Ctx->getObjectBuffer().getBuffer();
36-
if (Data.size() < llvm::ELF::EI_MAG3 + 1) {
50+
return ELF::EM_NONE;
51+
}
52+
53+
void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx) {
54+
StringRef Buffer = Ctx->getObjectBuffer().getBuffer();
55+
if (Buffer.size() < ELF::EI_MAG3 + 1) {
3756
Ctx->notifyFailed(make_error<JITLinkError>("Truncated ELF buffer"));
3857
return;
3958
}
4059

41-
if (!memcmp(Data.data(), llvm::ELF::ElfMagic, strlen(llvm::ELF::ElfMagic))) {
42-
if (Data.data()[llvm::ELF::EI_CLASS] == ELF::ELFCLASS64) {
43-
return jitLink_ELF_x86_64(std::move(Ctx));
44-
}
60+
if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) {
61+
Ctx->notifyFailed(make_error<JITLinkError>("ELF magic not valid"));
62+
return;
63+
}
64+
65+
Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
66+
if (!TargetMachineArch) {
67+
Ctx->notifyFailed(TargetMachineArch.takeError());
68+
return;
4569
}
4670

47-
Ctx->notifyFailed(make_error<JITLinkError>("ELF magic not valid"));
71+
switch (*TargetMachineArch) {
72+
case ELF::EM_X86_64:
73+
jitLink_ELF_x86_64(std::move(Ctx));
74+
return;
75+
default:
76+
Ctx->notifyFailed(make_error<JITLinkError>(
77+
"Unsupported target machine architecture in ELF object " +
78+
Ctx->getObjectBuffer().getBufferIdentifier()));
79+
return;
80+
}
4881
}
4982

5083
} // end namespace jitlink

0 commit comments

Comments
 (0)