15ffd83dbSDimitry Andric //===-------------- ELF.cpp - JIT linker function for ELF -------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // The LLVM Compiler Infrastructure 45ffd83dbSDimitry Andric // 55ffd83dbSDimitry Andric // This file is distributed under the University of Illinois Open Source 65ffd83dbSDimitry Andric // License. See LICENSE.TXT for details. 75ffd83dbSDimitry Andric // 85ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 95ffd83dbSDimitry Andric // 105ffd83dbSDimitry Andric // ELF jit-link function. 115ffd83dbSDimitry Andric // 125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 135ffd83dbSDimitry Andric 145ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF.h" 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELF.h" 175ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 18*e8d8bef9SDimitry Andric #include "llvm/Object/ELF.h" 195ffd83dbSDimitry Andric #include "llvm/Support/Endian.h" 205ffd83dbSDimitry Andric #include "llvm/Support/Format.h" 215ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h" 225ffd83dbSDimitry Andric #include <cstring> 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric using namespace llvm; 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric #define DEBUG_TYPE "jitlink" 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric namespace llvm { 295ffd83dbSDimitry Andric namespace jitlink { 305ffd83dbSDimitry Andric 31*e8d8bef9SDimitry Andric Expected<uint16_t> readTargetMachineArch(StringRef Buffer) { 32*e8d8bef9SDimitry Andric const char *Data = Buffer.data(); 335ffd83dbSDimitry Andric 34*e8d8bef9SDimitry Andric if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) { 35*e8d8bef9SDimitry Andric if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 36*e8d8bef9SDimitry Andric if (auto File = llvm::object::ELF64LEFile::create(Buffer)) { 37*e8d8bef9SDimitry Andric return File->getHeader().e_machine; 38*e8d8bef9SDimitry Andric } else { 39*e8d8bef9SDimitry Andric return File.takeError(); 40*e8d8bef9SDimitry Andric } 41*e8d8bef9SDimitry Andric } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 42*e8d8bef9SDimitry Andric if (auto File = llvm::object::ELF32LEFile::create(Buffer)) { 43*e8d8bef9SDimitry Andric return File->getHeader().e_machine; 44*e8d8bef9SDimitry Andric } else { 45*e8d8bef9SDimitry Andric return File.takeError(); 46*e8d8bef9SDimitry Andric } 47*e8d8bef9SDimitry Andric } 48*e8d8bef9SDimitry Andric } 495ffd83dbSDimitry Andric 50*e8d8bef9SDimitry Andric return ELF::EM_NONE; 51*e8d8bef9SDimitry Andric } 52*e8d8bef9SDimitry Andric 53*e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 54*e8d8bef9SDimitry Andric createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) { 55*e8d8bef9SDimitry Andric StringRef Buffer = ObjectBuffer.getBuffer(); 56*e8d8bef9SDimitry Andric if (Buffer.size() < ELF::EI_MAG3 + 1) 57*e8d8bef9SDimitry Andric return make_error<JITLinkError>("Truncated ELF buffer"); 58*e8d8bef9SDimitry Andric 59*e8d8bef9SDimitry Andric if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) 60*e8d8bef9SDimitry Andric return make_error<JITLinkError>("ELF magic not valid"); 61*e8d8bef9SDimitry Andric 62*e8d8bef9SDimitry Andric Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); 63*e8d8bef9SDimitry Andric if (!TargetMachineArch) 64*e8d8bef9SDimitry Andric return TargetMachineArch.takeError(); 65*e8d8bef9SDimitry Andric 66*e8d8bef9SDimitry Andric switch (*TargetMachineArch) { 67*e8d8bef9SDimitry Andric case ELF::EM_X86_64: 68*e8d8bef9SDimitry Andric return createLinkGraphFromELFObject_x86_64(std::move(ObjectBuffer)); 69*e8d8bef9SDimitry Andric default: 70*e8d8bef9SDimitry Andric return make_error<JITLinkError>( 71*e8d8bef9SDimitry Andric "Unsupported target machine architecture in ELF object " + 72*e8d8bef9SDimitry Andric ObjectBuffer.getBufferIdentifier()); 73*e8d8bef9SDimitry Andric } 74*e8d8bef9SDimitry Andric } 75*e8d8bef9SDimitry Andric 76*e8d8bef9SDimitry Andric void link_ELF(std::unique_ptr<LinkGraph> G, 77*e8d8bef9SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 78*e8d8bef9SDimitry Andric switch (G->getTargetTriple().getArch()) { 79*e8d8bef9SDimitry Andric case Triple::x86_64: 80*e8d8bef9SDimitry Andric link_ELF_x86_64(std::move(G), std::move(Ctx)); 81*e8d8bef9SDimitry Andric return; 82*e8d8bef9SDimitry Andric default: 83*e8d8bef9SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>( 84*e8d8bef9SDimitry Andric "Unsupported target machine architecture in ELF link graph " + 85*e8d8bef9SDimitry Andric G->getName())); 865ffd83dbSDimitry Andric return; 875ffd83dbSDimitry Andric } 885ffd83dbSDimitry Andric } 895ffd83dbSDimitry Andric 905ffd83dbSDimitry Andric } // end namespace jitlink 915ffd83dbSDimitry Andric } // end namespace llvm 92