15ffd83dbSDimitry Andric //===-------------- ELF.cpp - JIT linker function for ELF -------------===// 25ffd83dbSDimitry Andric // 3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // ELF jit-link function. 105ffd83dbSDimitry Andric // 115ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 125ffd83dbSDimitry Andric 135ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF.h" 145ffd83dbSDimitry Andric 155ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELF.h" 16*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" 17fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" 185ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 19e8d8bef9SDimitry Andric #include "llvm/Object/ELF.h" 205ffd83dbSDimitry Andric #include "llvm/Support/Endian.h" 215ffd83dbSDimitry Andric #include "llvm/Support/Format.h" 225ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h" 235ffd83dbSDimitry Andric #include <cstring> 245ffd83dbSDimitry Andric 255ffd83dbSDimitry Andric using namespace llvm; 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric #define DEBUG_TYPE "jitlink" 285ffd83dbSDimitry Andric 295ffd83dbSDimitry Andric namespace llvm { 305ffd83dbSDimitry Andric namespace jitlink { 315ffd83dbSDimitry Andric 32e8d8bef9SDimitry Andric Expected<uint16_t> readTargetMachineArch(StringRef Buffer) { 33e8d8bef9SDimitry Andric const char *Data = Buffer.data(); 345ffd83dbSDimitry Andric 35e8d8bef9SDimitry Andric if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) { 36e8d8bef9SDimitry Andric if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 37e8d8bef9SDimitry Andric if (auto File = llvm::object::ELF64LEFile::create(Buffer)) { 38e8d8bef9SDimitry Andric return File->getHeader().e_machine; 39e8d8bef9SDimitry Andric } else { 40e8d8bef9SDimitry Andric return File.takeError(); 41e8d8bef9SDimitry Andric } 42e8d8bef9SDimitry Andric } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 43e8d8bef9SDimitry Andric if (auto File = llvm::object::ELF32LEFile::create(Buffer)) { 44e8d8bef9SDimitry Andric return File->getHeader().e_machine; 45e8d8bef9SDimitry Andric } else { 46e8d8bef9SDimitry Andric return File.takeError(); 47e8d8bef9SDimitry Andric } 48e8d8bef9SDimitry Andric } 49e8d8bef9SDimitry Andric } 505ffd83dbSDimitry Andric 51e8d8bef9SDimitry Andric return ELF::EM_NONE; 52e8d8bef9SDimitry Andric } 53e8d8bef9SDimitry Andric 54e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 55e8d8bef9SDimitry Andric createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) { 56e8d8bef9SDimitry Andric StringRef Buffer = ObjectBuffer.getBuffer(); 57e8d8bef9SDimitry Andric if (Buffer.size() < ELF::EI_MAG3 + 1) 58e8d8bef9SDimitry Andric return make_error<JITLinkError>("Truncated ELF buffer"); 59e8d8bef9SDimitry Andric 60e8d8bef9SDimitry Andric if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) 61e8d8bef9SDimitry Andric return make_error<JITLinkError>("ELF magic not valid"); 62e8d8bef9SDimitry Andric 63e8d8bef9SDimitry Andric Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); 64e8d8bef9SDimitry Andric if (!TargetMachineArch) 65e8d8bef9SDimitry Andric return TargetMachineArch.takeError(); 66e8d8bef9SDimitry Andric 67e8d8bef9SDimitry Andric switch (*TargetMachineArch) { 68*349cc55cSDimitry Andric case ELF::EM_AARCH64: 69*349cc55cSDimitry Andric return createLinkGraphFromELFObject_aarch64(ObjectBuffer); 70fe6060f1SDimitry Andric case ELF::EM_RISCV: 71fe6060f1SDimitry Andric return createLinkGraphFromELFObject_riscv(ObjectBuffer); 72e8d8bef9SDimitry Andric case ELF::EM_X86_64: 73fe6060f1SDimitry Andric return createLinkGraphFromELFObject_x86_64(ObjectBuffer); 74e8d8bef9SDimitry Andric default: 75e8d8bef9SDimitry Andric return make_error<JITLinkError>( 76e8d8bef9SDimitry Andric "Unsupported target machine architecture in ELF object " + 77e8d8bef9SDimitry Andric ObjectBuffer.getBufferIdentifier()); 78e8d8bef9SDimitry Andric } 79e8d8bef9SDimitry Andric } 80e8d8bef9SDimitry Andric 81e8d8bef9SDimitry Andric void link_ELF(std::unique_ptr<LinkGraph> G, 82e8d8bef9SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 83e8d8bef9SDimitry Andric switch (G->getTargetTriple().getArch()) { 84*349cc55cSDimitry Andric case Triple::aarch64: 85*349cc55cSDimitry Andric link_ELF_aarch64(std::move(G), std::move(Ctx)); 86*349cc55cSDimitry Andric return; 87fe6060f1SDimitry Andric case Triple::riscv32: 88fe6060f1SDimitry Andric case Triple::riscv64: 89fe6060f1SDimitry Andric link_ELF_riscv(std::move(G), std::move(Ctx)); 90fe6060f1SDimitry Andric return; 91e8d8bef9SDimitry Andric case Triple::x86_64: 92e8d8bef9SDimitry Andric link_ELF_x86_64(std::move(G), std::move(Ctx)); 93e8d8bef9SDimitry Andric return; 94e8d8bef9SDimitry Andric default: 95e8d8bef9SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>( 96e8d8bef9SDimitry Andric "Unsupported target machine architecture in ELF link graph " + 97e8d8bef9SDimitry Andric G->getName())); 985ffd83dbSDimitry Andric return; 995ffd83dbSDimitry Andric } 1005ffd83dbSDimitry Andric } 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric } // end namespace jitlink 1035ffd83dbSDimitry Andric } // end namespace llvm 104