15ffd83dbSDimitry Andric //===-------------- ELF.cpp - JIT linker function for ELF -------------===// 25ffd83dbSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry 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" 1606c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h" 17349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" 18bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_i386.h" 19bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h" 2006c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" 21fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" 225ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 23e8d8bef9SDimitry Andric #include "llvm/Object/ELF.h" 245ffd83dbSDimitry Andric #include "llvm/Support/Format.h" 255ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h" 265ffd83dbSDimitry Andric #include <cstring> 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric using namespace llvm; 295ffd83dbSDimitry Andric 305ffd83dbSDimitry Andric #define DEBUG_TYPE "jitlink" 315ffd83dbSDimitry Andric 325ffd83dbSDimitry Andric namespace llvm { 335ffd83dbSDimitry Andric namespace jitlink { 345ffd83dbSDimitry Andric 35e8d8bef9SDimitry Andric Expected<uint16_t> readTargetMachineArch(StringRef Buffer) { 36e8d8bef9SDimitry Andric const char *Data = Buffer.data(); 375ffd83dbSDimitry Andric 38e8d8bef9SDimitry Andric if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) { 39e8d8bef9SDimitry Andric if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 40e8d8bef9SDimitry Andric if (auto File = llvm::object::ELF64LEFile::create(Buffer)) { 41e8d8bef9SDimitry Andric return File->getHeader().e_machine; 42e8d8bef9SDimitry Andric } else { 43e8d8bef9SDimitry Andric return File.takeError(); 44e8d8bef9SDimitry Andric } 45e8d8bef9SDimitry Andric } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 46e8d8bef9SDimitry Andric if (auto File = llvm::object::ELF32LEFile::create(Buffer)) { 47e8d8bef9SDimitry Andric return File->getHeader().e_machine; 48e8d8bef9SDimitry Andric } else { 49e8d8bef9SDimitry Andric return File.takeError(); 50e8d8bef9SDimitry Andric } 51e8d8bef9SDimitry Andric } 52e8d8bef9SDimitry Andric } 535ffd83dbSDimitry Andric 54*5f757f3fSDimitry Andric if (Data[ELF::EI_DATA] == ELF::ELFDATA2MSB) { 55*5f757f3fSDimitry Andric if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 56*5f757f3fSDimitry Andric if (auto File = llvm::object::ELF64BEFile::create(Buffer)) { 57*5f757f3fSDimitry Andric return File->getHeader().e_machine; 58*5f757f3fSDimitry Andric } else { 59*5f757f3fSDimitry Andric return File.takeError(); 60*5f757f3fSDimitry Andric } 61*5f757f3fSDimitry Andric } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 62*5f757f3fSDimitry Andric if (auto File = llvm::object::ELF32BEFile::create(Buffer)) { 63*5f757f3fSDimitry Andric return File->getHeader().e_machine; 64*5f757f3fSDimitry Andric } else { 65*5f757f3fSDimitry Andric return File.takeError(); 66*5f757f3fSDimitry Andric } 67*5f757f3fSDimitry Andric } 68*5f757f3fSDimitry Andric } 69*5f757f3fSDimitry Andric 70e8d8bef9SDimitry Andric return ELF::EM_NONE; 71e8d8bef9SDimitry Andric } 72e8d8bef9SDimitry Andric 73e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 74e8d8bef9SDimitry Andric createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) { 75e8d8bef9SDimitry Andric StringRef Buffer = ObjectBuffer.getBuffer(); 7606c3fb27SDimitry Andric if (Buffer.size() < ELF::EI_NIDENT) 77e8d8bef9SDimitry Andric return make_error<JITLinkError>("Truncated ELF buffer"); 78e8d8bef9SDimitry Andric 79e8d8bef9SDimitry Andric if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) 80e8d8bef9SDimitry Andric return make_error<JITLinkError>("ELF magic not valid"); 81e8d8bef9SDimitry Andric 8206c3fb27SDimitry Andric uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA]; 83e8d8bef9SDimitry Andric Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); 84e8d8bef9SDimitry Andric if (!TargetMachineArch) 85e8d8bef9SDimitry Andric return TargetMachineArch.takeError(); 86e8d8bef9SDimitry Andric 87e8d8bef9SDimitry Andric switch (*TargetMachineArch) { 88349cc55cSDimitry Andric case ELF::EM_AARCH64: 89349cc55cSDimitry Andric return createLinkGraphFromELFObject_aarch64(ObjectBuffer); 9006c3fb27SDimitry Andric case ELF::EM_ARM: 9106c3fb27SDimitry Andric return createLinkGraphFromELFObject_aarch32(ObjectBuffer); 92bdd1243dSDimitry Andric case ELF::EM_LOONGARCH: 93bdd1243dSDimitry Andric return createLinkGraphFromELFObject_loongarch(ObjectBuffer); 9406c3fb27SDimitry Andric case ELF::EM_PPC64: { 9506c3fb27SDimitry Andric if (DataEncoding == ELF::ELFDATA2LSB) 9606c3fb27SDimitry Andric return createLinkGraphFromELFObject_ppc64le(ObjectBuffer); 9706c3fb27SDimitry Andric else 9806c3fb27SDimitry Andric return createLinkGraphFromELFObject_ppc64(ObjectBuffer); 9906c3fb27SDimitry Andric } 100fe6060f1SDimitry Andric case ELF::EM_RISCV: 101fe6060f1SDimitry Andric return createLinkGraphFromELFObject_riscv(ObjectBuffer); 102e8d8bef9SDimitry Andric case ELF::EM_X86_64: 103fe6060f1SDimitry Andric return createLinkGraphFromELFObject_x86_64(ObjectBuffer); 104bdd1243dSDimitry Andric case ELF::EM_386: 105bdd1243dSDimitry Andric return createLinkGraphFromELFObject_i386(ObjectBuffer); 106e8d8bef9SDimitry Andric default: 107e8d8bef9SDimitry Andric return make_error<JITLinkError>( 108e8d8bef9SDimitry Andric "Unsupported target machine architecture in ELF object " + 109e8d8bef9SDimitry Andric ObjectBuffer.getBufferIdentifier()); 110e8d8bef9SDimitry Andric } 111e8d8bef9SDimitry Andric } 112e8d8bef9SDimitry Andric 113e8d8bef9SDimitry Andric void link_ELF(std::unique_ptr<LinkGraph> G, 114e8d8bef9SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 115e8d8bef9SDimitry Andric switch (G->getTargetTriple().getArch()) { 116349cc55cSDimitry Andric case Triple::aarch64: 117349cc55cSDimitry Andric link_ELF_aarch64(std::move(G), std::move(Ctx)); 118349cc55cSDimitry Andric return; 11906c3fb27SDimitry Andric case Triple::arm: 12006c3fb27SDimitry Andric case Triple::armeb: 12106c3fb27SDimitry Andric case Triple::thumb: 12206c3fb27SDimitry Andric case Triple::thumbeb: 12306c3fb27SDimitry Andric link_ELF_aarch32(std::move(G), std::move(Ctx)); 12406c3fb27SDimitry Andric return; 125bdd1243dSDimitry Andric case Triple::loongarch32: 126bdd1243dSDimitry Andric case Triple::loongarch64: 127bdd1243dSDimitry Andric link_ELF_loongarch(std::move(G), std::move(Ctx)); 128bdd1243dSDimitry Andric return; 12906c3fb27SDimitry Andric case Triple::ppc64: 13006c3fb27SDimitry Andric link_ELF_ppc64(std::move(G), std::move(Ctx)); 13106c3fb27SDimitry Andric return; 13206c3fb27SDimitry Andric case Triple::ppc64le: 13306c3fb27SDimitry Andric link_ELF_ppc64le(std::move(G), std::move(Ctx)); 13406c3fb27SDimitry Andric return; 135fe6060f1SDimitry Andric case Triple::riscv32: 136fe6060f1SDimitry Andric case Triple::riscv64: 137fe6060f1SDimitry Andric link_ELF_riscv(std::move(G), std::move(Ctx)); 138fe6060f1SDimitry Andric return; 139e8d8bef9SDimitry Andric case Triple::x86_64: 140e8d8bef9SDimitry Andric link_ELF_x86_64(std::move(G), std::move(Ctx)); 141e8d8bef9SDimitry Andric return; 142bdd1243dSDimitry Andric case Triple::x86: 143bdd1243dSDimitry Andric link_ELF_i386(std::move(G), std::move(Ctx)); 144bdd1243dSDimitry Andric return; 145e8d8bef9SDimitry Andric default: 146e8d8bef9SDimitry Andric Ctx->notifyFailed(make_error<JITLinkError>( 147e8d8bef9SDimitry Andric "Unsupported target machine architecture in ELF link graph " + 148e8d8bef9SDimitry Andric G->getName())); 1495ffd83dbSDimitry Andric return; 1505ffd83dbSDimitry Andric } 1515ffd83dbSDimitry Andric } 1525ffd83dbSDimitry Andric 1535ffd83dbSDimitry Andric } // end namespace jitlink 1545ffd83dbSDimitry Andric } // end namespace llvm 155