forked from OSchip/llvm-project
[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
This commit is contained in:
parent
2d1b024d06
commit
83b52b5ba2
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "llvm/BinaryFormat/ELF.h"
|
#include "llvm/BinaryFormat/ELF.h"
|
||||||
#include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
|
#include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
|
||||||
|
#include "llvm/Object/ELF.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
@ -27,24 +28,56 @@ using namespace llvm;
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace jitlink {
|
namespace jitlink {
|
||||||
|
|
||||||
|
Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
|
||||||
|
const char *Data = Buffer.data();
|
||||||
|
|
||||||
|
if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
|
||||||
|
if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
|
||||||
|
if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
|
||||||
|
return File->getHeader().e_machine;
|
||||||
|
} else {
|
||||||
|
return File.takeError();
|
||||||
|
}
|
||||||
|
} else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
|
||||||
|
if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
|
||||||
|
return File->getHeader().e_machine;
|
||||||
|
} else {
|
||||||
|
return File.takeError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ELF::EM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx) {
|
void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx) {
|
||||||
|
StringRef Buffer = Ctx->getObjectBuffer().getBuffer();
|
||||||
// We don't want to do full ELF validation here. We just verify it is elf'ish.
|
if (Buffer.size() < ELF::EI_MAG3 + 1) {
|
||||||
// Probably should parse into an elf header when we support more than x86 :)
|
|
||||||
|
|
||||||
StringRef Data = Ctx->getObjectBuffer().getBuffer();
|
|
||||||
if (Data.size() < llvm::ELF::EI_MAG3 + 1) {
|
|
||||||
Ctx->notifyFailed(make_error<JITLinkError>("Truncated ELF buffer"));
|
Ctx->notifyFailed(make_error<JITLinkError>("Truncated ELF buffer"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memcmp(Data.data(), llvm::ELF::ElfMagic, strlen(llvm::ELF::ElfMagic))) {
|
if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) {
|
||||||
if (Data.data()[llvm::ELF::EI_CLASS] == ELF::ELFCLASS64) {
|
Ctx->notifyFailed(make_error<JITLinkError>("ELF magic not valid"));
|
||||||
return jitLink_ELF_x86_64(std::move(Ctx));
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ctx->notifyFailed(make_error<JITLinkError>("ELF magic not valid"));
|
Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
|
||||||
|
if (!TargetMachineArch) {
|
||||||
|
Ctx->notifyFailed(TargetMachineArch.takeError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*TargetMachineArch) {
|
||||||
|
case ELF::EM_X86_64:
|
||||||
|
jitLink_ELF_x86_64(std::move(Ctx));
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
Ctx->notifyFailed(make_error<JITLinkError>(
|
||||||
|
"Unsupported target machine architecture in ELF object " +
|
||||||
|
Ctx->getObjectBuffer().getBufferIdentifier()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace jitlink
|
} // end namespace jitlink
|
||||||
|
|
Loading…
Reference in New Issue