1 //===-------------- ELF.cpp - JIT linker function for ELF -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // ELF jit-link function. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/JITLink/ELF.h" 14 15 #include "llvm/BinaryFormat/ELF.h" 16 #include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h" 17 #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" 18 #include "llvm/ExecutionEngine/JITLink/ELF_i386.h" 19 #include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h" 20 #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" 21 #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" 22 #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 23 #include "llvm/Object/ELF.h" 24 #include <cstring> 25 26 using namespace llvm; 27 28 #define DEBUG_TYPE "jitlink" 29 30 namespace llvm { 31 namespace jitlink { 32 33 Expected<uint16_t> readTargetMachineArch(StringRef Buffer) { 34 const char *Data = Buffer.data(); 35 36 if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) { 37 if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 38 if (auto File = llvm::object::ELF64LEFile::create(Buffer)) { 39 return File->getHeader().e_machine; 40 } else { 41 return File.takeError(); 42 } 43 } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 44 if (auto File = llvm::object::ELF32LEFile::create(Buffer)) { 45 return File->getHeader().e_machine; 46 } else { 47 return File.takeError(); 48 } 49 } 50 } 51 52 if (Data[ELF::EI_DATA] == ELF::ELFDATA2MSB) { 53 if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) { 54 if (auto File = llvm::object::ELF64BEFile::create(Buffer)) { 55 return File->getHeader().e_machine; 56 } else { 57 return File.takeError(); 58 } 59 } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) { 60 if (auto File = llvm::object::ELF32BEFile::create(Buffer)) { 61 return File->getHeader().e_machine; 62 } else { 63 return File.takeError(); 64 } 65 } 66 } 67 68 return ELF::EM_NONE; 69 } 70 71 Expected<std::unique_ptr<LinkGraph>> 72 createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer, 73 std::shared_ptr<orc::SymbolStringPool> SSP) { 74 StringRef Buffer = ObjectBuffer.getBuffer(); 75 if (Buffer.size() < ELF::EI_NIDENT) 76 return make_error<JITLinkError>("Truncated ELF buffer"); 77 78 if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0) 79 return make_error<JITLinkError>("ELF magic not valid"); 80 81 uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA]; 82 Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer); 83 if (!TargetMachineArch) 84 return TargetMachineArch.takeError(); 85 86 switch (*TargetMachineArch) { 87 case ELF::EM_AARCH64: 88 return createLinkGraphFromELFObject_aarch64(ObjectBuffer, std::move(SSP)); 89 case ELF::EM_ARM: 90 return createLinkGraphFromELFObject_aarch32(ObjectBuffer, std::move(SSP)); 91 case ELF::EM_PPC64: { 92 if (DataEncoding == ELF::ELFDATA2LSB) 93 return createLinkGraphFromELFObject_ppc64le(ObjectBuffer, std::move(SSP)); 94 else 95 return createLinkGraphFromELFObject_ppc64(ObjectBuffer, std::move(SSP)); 96 } 97 case ELF::EM_LOONGARCH: 98 return createLinkGraphFromELFObject_loongarch(ObjectBuffer, std::move(SSP)); 99 case ELF::EM_RISCV: 100 return createLinkGraphFromELFObject_riscv(ObjectBuffer, std::move(SSP)); 101 case ELF::EM_X86_64: 102 return createLinkGraphFromELFObject_x86_64(ObjectBuffer, std::move(SSP)); 103 case ELF::EM_386: 104 return createLinkGraphFromELFObject_i386(ObjectBuffer, std::move(SSP)); 105 default: 106 return make_error<JITLinkError>( 107 "Unsupported target machine architecture in ELF object " + 108 ObjectBuffer.getBufferIdentifier()); 109 } 110 } 111 112 void link_ELF(std::unique_ptr<LinkGraph> G, 113 std::unique_ptr<JITLinkContext> Ctx) { 114 switch (G->getTargetTriple().getArch()) { 115 case Triple::aarch64: 116 link_ELF_aarch64(std::move(G), std::move(Ctx)); 117 return; 118 case Triple::arm: 119 case Triple::armeb: 120 case Triple::thumb: 121 case Triple::thumbeb: 122 link_ELF_aarch32(std::move(G), std::move(Ctx)); 123 return; 124 case Triple::loongarch32: 125 case Triple::loongarch64: 126 link_ELF_loongarch(std::move(G), std::move(Ctx)); 127 return; 128 case Triple::ppc64: 129 link_ELF_ppc64(std::move(G), std::move(Ctx)); 130 return; 131 case Triple::ppc64le: 132 link_ELF_ppc64le(std::move(G), std::move(Ctx)); 133 return; 134 case Triple::riscv32: 135 case Triple::riscv64: 136 link_ELF_riscv(std::move(G), std::move(Ctx)); 137 return; 138 case Triple::x86_64: 139 link_ELF_x86_64(std::move(G), std::move(Ctx)); 140 return; 141 case Triple::x86: 142 link_ELF_i386(std::move(G), std::move(Ctx)); 143 return; 144 default: 145 Ctx->notifyFailed(make_error<JITLinkError>( 146 "Unsupported target machine architecture in ELF link graph " + 147 G->getName())); 148 return; 149 } 150 } 151 152 } // end namespace jitlink 153 } // end namespace llvm 154