| 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_loongarch.h" |
| 19 | #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" |
| 20 | #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" |
| 21 | #include "llvm/ExecutionEngine/JITLink/ELF_x86.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(Object: 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(Object: 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(Object: 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(Object: 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>(Args: "Truncated ELF buffer" ); |
| 77 | |
| 78 | if (memcmp(s1: Buffer.data(), s2: ELF::ElfMagic, n: strlen(s: ELF::ElfMagic)) != 0) |
| 79 | return make_error<JITLinkError>(Args: "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, SSP: std::move(SSP)); |
| 89 | case ELF::EM_ARM: |
| 90 | return createLinkGraphFromELFObject_aarch32(ObjectBuffer, SSP: std::move(SSP)); |
| 91 | case ELF::EM_PPC64: { |
| 92 | if (DataEncoding == ELF::ELFDATA2LSB) |
| 93 | return createLinkGraphFromELFObject_ppc64le(ObjectBuffer, SSP: std::move(SSP)); |
| 94 | else |
| 95 | return createLinkGraphFromELFObject_ppc64(ObjectBuffer, SSP: std::move(SSP)); |
| 96 | } |
| 97 | case ELF::EM_LOONGARCH: |
| 98 | return createLinkGraphFromELFObject_loongarch(ObjectBuffer, SSP: std::move(SSP)); |
| 99 | case ELF::EM_RISCV: |
| 100 | return createLinkGraphFromELFObject_riscv(ObjectBuffer, SSP: std::move(SSP)); |
| 101 | case ELF::EM_X86_64: |
| 102 | return createLinkGraphFromELFObject_x86_64(ObjectBuffer, SSP: std::move(SSP)); |
| 103 | case ELF::EM_386: |
| 104 | return createLinkGraphFromELFObject_x86(ObjectBuffer, SSP: std::move(SSP)); |
| 105 | default: |
| 106 | return make_error<JITLinkError>( |
| 107 | Args: "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(G: std::move(G), Ctx: 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(G: std::move(G), Ctx: std::move(Ctx)); |
| 123 | return; |
| 124 | case Triple::loongarch32: |
| 125 | case Triple::loongarch64: |
| 126 | link_ELF_loongarch(G: std::move(G), Ctx: std::move(Ctx)); |
| 127 | return; |
| 128 | case Triple::ppc64: |
| 129 | link_ELF_ppc64(G: std::move(G), Ctx: std::move(Ctx)); |
| 130 | return; |
| 131 | case Triple::ppc64le: |
| 132 | link_ELF_ppc64le(G: std::move(G), Ctx: std::move(Ctx)); |
| 133 | return; |
| 134 | case Triple::riscv32: |
| 135 | case Triple::riscv64: |
| 136 | link_ELF_riscv(G: std::move(G), Ctx: std::move(Ctx)); |
| 137 | return; |
| 138 | case Triple::x86_64: |
| 139 | link_ELF_x86_64(G: std::move(G), Ctx: std::move(Ctx)); |
| 140 | return; |
| 141 | case Triple::x86: |
| 142 | link_ELF_x86(G: std::move(G), Ctx: std::move(Ctx)); |
| 143 | return; |
| 144 | default: |
| 145 | Ctx->notifyFailed(Err: make_error<JITLinkError>( |
| 146 | Args: "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 | |