12e40cf06SLang Hames //===-------------- ELF.cpp - JIT linker function for ELF -------------===// 22e40cf06SLang Hames // 3c874dd53SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c874dd53SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information. 5c874dd53SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62e40cf06SLang Hames // 72e40cf06SLang Hames //===----------------------------------------------------------------------===// 82e40cf06SLang Hames // 92e40cf06SLang Hames // ELF jit-link function. 102e40cf06SLang Hames // 112e40cf06SLang Hames //===----------------------------------------------------------------------===// 122e40cf06SLang Hames 132e40cf06SLang Hames #include "llvm/ExecutionEngine/JITLink/ELF.h" 142e40cf06SLang Hames 152e40cf06SLang Hames #include "llvm/BinaryFormat/ELF.h" 165c1d160cSStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h" 172ed91da0SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" 1829fe204bSKshitij Jain #include "llvm/ExecutionEngine/JITLink/ELF_i386.h" 19f10d452dSwanglei #include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h" 208313507aSLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" 210ad562b4Sluxufan #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" 222e40cf06SLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 2383b52b5bSStefan Gränitz #include "llvm/Object/ELF.h" 242e40cf06SLang Hames #include <cstring> 252e40cf06SLang Hames 262e40cf06SLang Hames using namespace llvm; 272e40cf06SLang Hames 282e40cf06SLang Hames #define DEBUG_TYPE "jitlink" 292e40cf06SLang Hames 302e40cf06SLang Hames namespace llvm { 312e40cf06SLang Hames namespace jitlink { 322e40cf06SLang Hames 3383b52b5bSStefan Gränitz Expected<uint16_t> readTargetMachineArch(StringRef Buffer) { 3483b52b5bSStefan Gränitz const char *Data = Buffer.data(); 3583b52b5bSStefan Gränitz 3683b52b5bSStefan Gränitz if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) { 3783b52b5bSStefan Gränitz if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 3883b52b5bSStefan Gränitz if (auto File = llvm::object::ELF64LEFile::create(Buffer)) { 3983b52b5bSStefan Gränitz return File->getHeader().e_machine; 4083b52b5bSStefan Gränitz } else { 4183b52b5bSStefan Gränitz return File.takeError(); 4283b52b5bSStefan Gränitz } 4383b52b5bSStefan Gränitz } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 4483b52b5bSStefan Gränitz if (auto File = llvm::object::ELF32LEFile::create(Buffer)) { 4583b52b5bSStefan Gränitz return File->getHeader().e_machine; 4683b52b5bSStefan Gränitz } else { 4783b52b5bSStefan Gränitz return File.takeError(); 4883b52b5bSStefan Gränitz } 4983b52b5bSStefan Gränitz } 5083b52b5bSStefan Gränitz } 5183b52b5bSStefan Gränitz 52be7a5465SKai Luo if (Data[ELF::EI_DATA] == ELF::ELFDATA2MSB) { 53be7a5465SKai Luo if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 54be7a5465SKai Luo if (auto File = llvm::object::ELF64BEFile::create(Buffer)) { 55be7a5465SKai Luo return File->getHeader().e_machine; 56be7a5465SKai Luo } else { 57be7a5465SKai Luo return File.takeError(); 58be7a5465SKai Luo } 59be7a5465SKai Luo } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 60be7a5465SKai Luo if (auto File = llvm::object::ELF32BEFile::create(Buffer)) { 61be7a5465SKai Luo return File->getHeader().e_machine; 62be7a5465SKai Luo } else { 63be7a5465SKai Luo return File.takeError(); 64be7a5465SKai Luo } 65be7a5465SKai Luo } 66be7a5465SKai Luo } 67be7a5465SKai Luo 6883b52b5bSStefan Gränitz return ELF::EM_NONE; 6983b52b5bSStefan Gränitz } 7083b52b5bSStefan Gränitz 71ec6b71dfSLang Hames Expected<std::unique_ptr<LinkGraph>> 72*2ccf7ed2SJared Wyles createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer, 73*2ccf7ed2SJared Wyles std::shared_ptr<orc::SymbolStringPool> SSP) { 74ec6b71dfSLang Hames StringRef Buffer = ObjectBuffer.getBuffer(); 75d8472ac2SLang Hames if (Buffer.size() < ELF::EI_NIDENT) 76ec6b71dfSLang Hames return make_error<JITLinkError>("Truncated ELF buffer"); 772e40cf06SLang Hames 78ec6b71dfSLang Hames if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) 79ec6b71dfSLang Hames return make_error<JITLinkError>("ELF magic not valid"); 802e40cf06SLang Hames 818313507aSLang Hames uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA]; 8283b52b5bSStefan Gränitz Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); 83ec6b71dfSLang Hames if (!TargetMachineArch) 84ec6b71dfSLang Hames return TargetMachineArch.takeError(); 8583b52b5bSStefan Gränitz 8683b52b5bSStefan Gränitz switch (*TargetMachineArch) { 872ed91da0SStefan Gränitz case ELF::EM_AARCH64: 88*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_aarch64(ObjectBuffer, std::move(SSP)); 895c1d160cSStefan Gränitz case ELF::EM_ARM: 90*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_aarch32(ObjectBuffer, std::move(SSP)); 918313507aSLang Hames case ELF::EM_PPC64: { 928313507aSLang Hames if (DataEncoding == ELF::ELFDATA2LSB) 93*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_ppc64le(ObjectBuffer, std::move(SSP)); 948313507aSLang Hames else 95*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_ppc64(ObjectBuffer, std::move(SSP)); 968313507aSLang Hames } 97*2ccf7ed2SJared Wyles case ELF::EM_LOONGARCH: 98*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_loongarch(ObjectBuffer, std::move(SSP)); 990ad562b4Sluxufan case ELF::EM_RISCV: 100*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_riscv(ObjectBuffer, std::move(SSP)); 10183b52b5bSStefan Gränitz case ELF::EM_X86_64: 102*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_x86_64(ObjectBuffer, std::move(SSP)); 10329fe204bSKshitij Jain case ELF::EM_386: 104*2ccf7ed2SJared Wyles return createLinkGraphFromELFObject_i386(ObjectBuffer, std::move(SSP)); 105ec6b71dfSLang Hames default: 106ec6b71dfSLang Hames return make_error<JITLinkError>( 107ec6b71dfSLang Hames "Unsupported target machine architecture in ELF object " + 108ec6b71dfSLang Hames ObjectBuffer.getBufferIdentifier()); 109ec6b71dfSLang Hames } 110ec6b71dfSLang Hames } 111ec6b71dfSLang Hames 112ec6b71dfSLang Hames void link_ELF(std::unique_ptr<LinkGraph> G, 113ec6b71dfSLang Hames std::unique_ptr<JITLinkContext> Ctx) { 114ec6b71dfSLang Hames switch (G->getTargetTriple().getArch()) { 1152ed91da0SStefan Gränitz case Triple::aarch64: 1162ed91da0SStefan Gränitz link_ELF_aarch64(std::move(G), std::move(Ctx)); 1172ed91da0SStefan Gränitz return; 1185c1d160cSStefan Gränitz case Triple::arm: 1195c1d160cSStefan Gränitz case Triple::armeb: 1205c1d160cSStefan Gränitz case Triple::thumb: 1215c1d160cSStefan Gränitz case Triple::thumbeb: 1225c1d160cSStefan Gränitz link_ELF_aarch32(std::move(G), std::move(Ctx)); 1235c1d160cSStefan Gränitz return; 124f10d452dSwanglei case Triple::loongarch32: 125f10d452dSwanglei case Triple::loongarch64: 126f10d452dSwanglei link_ELF_loongarch(std::move(G), std::move(Ctx)); 127f10d452dSwanglei return; 1288313507aSLang Hames case Triple::ppc64: 1298313507aSLang Hames link_ELF_ppc64(std::move(G), std::move(Ctx)); 1308313507aSLang Hames return; 1318313507aSLang Hames case Triple::ppc64le: 1328313507aSLang Hames link_ELF_ppc64le(std::move(G), std::move(Ctx)); 1338313507aSLang Hames return; 1340ad562b4Sluxufan case Triple::riscv32: 1350ad562b4Sluxufan case Triple::riscv64: 1360ad562b4Sluxufan link_ELF_riscv(std::move(G), std::move(Ctx)); 1370ad562b4Sluxufan return; 138ec6b71dfSLang Hames case Triple::x86_64: 139ec6b71dfSLang Hames link_ELF_x86_64(std::move(G), std::move(Ctx)); 14083b52b5bSStefan Gränitz return; 14129fe204bSKshitij Jain case Triple::x86: 14229fe204bSKshitij Jain link_ELF_i386(std::move(G), std::move(Ctx)); 14329fe204bSKshitij Jain return; 14483b52b5bSStefan Gränitz default: 14583b52b5bSStefan Gränitz Ctx->notifyFailed(make_error<JITLinkError>( 146ec6b71dfSLang Hames "Unsupported target machine architecture in ELF link graph " + 147ec6b71dfSLang Hames G->getName())); 14883b52b5bSStefan Gränitz return; 14983b52b5bSStefan Gränitz } 1502e40cf06SLang Hames } 1512e40cf06SLang Hames 1522e40cf06SLang Hames } // end namespace jitlink 1532e40cf06SLang Hames } // end namespace llvm 154