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" 16*2ed91da0SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" 170ad562b4Sluxufan #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" 182e40cf06SLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 1983b52b5bSStefan Gränitz #include "llvm/Object/ELF.h" 202e40cf06SLang Hames #include "llvm/Support/Endian.h" 212e40cf06SLang Hames #include "llvm/Support/Format.h" 222e40cf06SLang Hames #include "llvm/Support/MemoryBuffer.h" 232e40cf06SLang Hames #include <cstring> 242e40cf06SLang Hames 252e40cf06SLang Hames using namespace llvm; 262e40cf06SLang Hames 272e40cf06SLang Hames #define DEBUG_TYPE "jitlink" 282e40cf06SLang Hames 292e40cf06SLang Hames namespace llvm { 302e40cf06SLang Hames namespace jitlink { 312e40cf06SLang Hames readTargetMachineArch(StringRef Buffer)3283b52b5bSStefan GränitzExpected<uint16_t> readTargetMachineArch(StringRef Buffer) { 3383b52b5bSStefan Gränitz const char *Data = Buffer.data(); 3483b52b5bSStefan Gränitz 3583b52b5bSStefan Gränitz if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) { 3683b52b5bSStefan Gränitz if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 3783b52b5bSStefan Gränitz if (auto File = llvm::object::ELF64LEFile::create(Buffer)) { 3883b52b5bSStefan Gränitz return File->getHeader().e_machine; 3983b52b5bSStefan Gränitz } else { 4083b52b5bSStefan Gränitz return File.takeError(); 4183b52b5bSStefan Gränitz } 4283b52b5bSStefan Gränitz } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 4383b52b5bSStefan Gränitz if (auto File = llvm::object::ELF32LEFile::create(Buffer)) { 4483b52b5bSStefan Gränitz return File->getHeader().e_machine; 4583b52b5bSStefan Gränitz } else { 4683b52b5bSStefan Gränitz return File.takeError(); 4783b52b5bSStefan Gränitz } 4883b52b5bSStefan Gränitz } 4983b52b5bSStefan Gränitz } 5083b52b5bSStefan Gränitz 5183b52b5bSStefan Gränitz return ELF::EM_NONE; 5283b52b5bSStefan Gränitz } 5383b52b5bSStefan Gränitz 54ec6b71dfSLang Hames Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer)55ec6b71dfSLang HamescreateLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) { 56ec6b71dfSLang Hames StringRef Buffer = ObjectBuffer.getBuffer(); 57ec6b71dfSLang Hames if (Buffer.size() < ELF::EI_MAG3 + 1) 58ec6b71dfSLang Hames return make_error<JITLinkError>("Truncated ELF buffer"); 592e40cf06SLang Hames 60ec6b71dfSLang Hames if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) 61ec6b71dfSLang Hames return make_error<JITLinkError>("ELF magic not valid"); 622e40cf06SLang Hames 6383b52b5bSStefan Gränitz Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); 64ec6b71dfSLang Hames if (!TargetMachineArch) 65ec6b71dfSLang Hames return TargetMachineArch.takeError(); 6683b52b5bSStefan Gränitz 6783b52b5bSStefan Gränitz switch (*TargetMachineArch) { 68*2ed91da0SStefan Gränitz case ELF::EM_AARCH64: 69*2ed91da0SStefan Gränitz return createLinkGraphFromELFObject_aarch64(ObjectBuffer); 700ad562b4Sluxufan case ELF::EM_RISCV: 710ad562b4Sluxufan return createLinkGraphFromELFObject_riscv(ObjectBuffer); 7283b52b5bSStefan Gränitz case ELF::EM_X86_64: 73949d1d99SStefan Gränitz return createLinkGraphFromELFObject_x86_64(ObjectBuffer); 74ec6b71dfSLang Hames default: 75ec6b71dfSLang Hames return make_error<JITLinkError>( 76ec6b71dfSLang Hames "Unsupported target machine architecture in ELF object " + 77ec6b71dfSLang Hames ObjectBuffer.getBufferIdentifier()); 78ec6b71dfSLang Hames } 79ec6b71dfSLang Hames } 80ec6b71dfSLang Hames link_ELF(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)81ec6b71dfSLang Hamesvoid link_ELF(std::unique_ptr<LinkGraph> G, 82ec6b71dfSLang Hames std::unique_ptr<JITLinkContext> Ctx) { 83ec6b71dfSLang Hames switch (G->getTargetTriple().getArch()) { 84*2ed91da0SStefan Gränitz case Triple::aarch64: 85*2ed91da0SStefan Gränitz link_ELF_aarch64(std::move(G), std::move(Ctx)); 86*2ed91da0SStefan Gränitz return; 870ad562b4Sluxufan case Triple::riscv32: 880ad562b4Sluxufan case Triple::riscv64: 890ad562b4Sluxufan link_ELF_riscv(std::move(G), std::move(Ctx)); 900ad562b4Sluxufan return; 91ec6b71dfSLang Hames case Triple::x86_64: 92ec6b71dfSLang Hames link_ELF_x86_64(std::move(G), std::move(Ctx)); 9383b52b5bSStefan Gränitz return; 9483b52b5bSStefan Gränitz default: 9583b52b5bSStefan Gränitz Ctx->notifyFailed(make_error<JITLinkError>( 96ec6b71dfSLang Hames "Unsupported target machine architecture in ELF link graph " + 97ec6b71dfSLang Hames G->getName())); 9883b52b5bSStefan Gränitz return; 9983b52b5bSStefan Gränitz } 1002e40cf06SLang Hames } 1012e40cf06SLang Hames 1022e40cf06SLang Hames } // end namespace jitlink 1032e40cf06SLang Hames } // end namespace llvm 104