From: Stefan Gränitz Date: Tue, 8 Dec 2020 09:53:50 +0000 (+0100) Subject: [JITLink][ELF] Route objects to their matching linker backends based on header info X-Git-Tag: llvmorg-13-init~4082 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=83b52b5ba27815200e76343f2a2f1614bb1960d9;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp index 6160583..19b8782 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp @@ -15,6 +15,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" +#include "llvm/Object/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" @@ -27,24 +28,56 @@ using namespace llvm; namespace llvm { namespace jitlink { -void jitLink_ELF(std::unique_ptr Ctx) { +Expected readTargetMachineArch(StringRef Buffer) { + const char *Data = Buffer.data(); - // We don't want to do full ELF validation here. We just verify it is elf'ish. - // Probably should parse into an elf header when we support more than x86 :) + 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(); + } + } + } - StringRef Data = Ctx->getObjectBuffer().getBuffer(); - if (Data.size() < llvm::ELF::EI_MAG3 + 1) { + return ELF::EM_NONE; +} + +void jitLink_ELF(std::unique_ptr Ctx) { + StringRef Buffer = Ctx->getObjectBuffer().getBuffer(); + if (Buffer.size() < ELF::EI_MAG3 + 1) { Ctx->notifyFailed(make_error("Truncated ELF buffer")); return; } - if (!memcmp(Data.data(), llvm::ELF::ElfMagic, strlen(llvm::ELF::ElfMagic))) { - if (Data.data()[llvm::ELF::EI_CLASS] == ELF::ELFCLASS64) { - return jitLink_ELF_x86_64(std::move(Ctx)); - } + if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) { + Ctx->notifyFailed(make_error("ELF magic not valid")); + return; + } + + Expected TargetMachineArch = readTargetMachineArch(Buffer); + if (!TargetMachineArch) { + Ctx->notifyFailed(TargetMachineArch.takeError()); + return; } - Ctx->notifyFailed(make_error("ELF magic not valid")); + switch (*TargetMachineArch) { + case ELF::EM_X86_64: + jitLink_ELF_x86_64(std::move(Ctx)); + return; + default: + Ctx->notifyFailed(make_error( + "Unsupported target machine architecture in ELF object " + + Ctx->getObjectBuffer().getBufferIdentifier())); + return; + } } } // end namespace jitlink