xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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"
16*06c3fb27SDimitry 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"
20*06c3fb27SDimitry 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/Endian.h"
255ffd83dbSDimitry Andric #include "llvm/Support/Format.h"
265ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
275ffd83dbSDimitry Andric #include <cstring>
285ffd83dbSDimitry Andric 
295ffd83dbSDimitry Andric using namespace llvm;
305ffd83dbSDimitry Andric 
315ffd83dbSDimitry Andric #define DEBUG_TYPE "jitlink"
325ffd83dbSDimitry Andric 
335ffd83dbSDimitry Andric namespace llvm {
345ffd83dbSDimitry Andric namespace jitlink {
355ffd83dbSDimitry Andric 
36e8d8bef9SDimitry Andric Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
37e8d8bef9SDimitry Andric   const char *Data = Buffer.data();
385ffd83dbSDimitry Andric 
39e8d8bef9SDimitry Andric   if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
40e8d8bef9SDimitry Andric     if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
41e8d8bef9SDimitry Andric       if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
42e8d8bef9SDimitry Andric         return File->getHeader().e_machine;
43e8d8bef9SDimitry Andric       } else {
44e8d8bef9SDimitry Andric         return File.takeError();
45e8d8bef9SDimitry Andric       }
46e8d8bef9SDimitry Andric     } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
47e8d8bef9SDimitry Andric       if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
48e8d8bef9SDimitry Andric         return File->getHeader().e_machine;
49e8d8bef9SDimitry Andric       } else {
50e8d8bef9SDimitry Andric         return File.takeError();
51e8d8bef9SDimitry Andric       }
52e8d8bef9SDimitry Andric     }
53e8d8bef9SDimitry Andric   }
545ffd83dbSDimitry Andric 
55e8d8bef9SDimitry Andric   return ELF::EM_NONE;
56e8d8bef9SDimitry Andric }
57e8d8bef9SDimitry Andric 
58e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>>
59e8d8bef9SDimitry Andric createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
60e8d8bef9SDimitry Andric   StringRef Buffer = ObjectBuffer.getBuffer();
61*06c3fb27SDimitry Andric   if (Buffer.size() < ELF::EI_NIDENT)
62e8d8bef9SDimitry Andric     return make_error<JITLinkError>("Truncated ELF buffer");
63e8d8bef9SDimitry Andric 
64e8d8bef9SDimitry Andric   if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
65e8d8bef9SDimitry Andric     return make_error<JITLinkError>("ELF magic not valid");
66e8d8bef9SDimitry Andric 
67*06c3fb27SDimitry Andric   uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA];
68e8d8bef9SDimitry Andric   Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
69e8d8bef9SDimitry Andric   if (!TargetMachineArch)
70e8d8bef9SDimitry Andric     return TargetMachineArch.takeError();
71e8d8bef9SDimitry Andric 
72e8d8bef9SDimitry Andric   switch (*TargetMachineArch) {
73349cc55cSDimitry Andric   case ELF::EM_AARCH64:
74349cc55cSDimitry Andric     return createLinkGraphFromELFObject_aarch64(ObjectBuffer);
75*06c3fb27SDimitry Andric   case ELF::EM_ARM:
76*06c3fb27SDimitry Andric     return createLinkGraphFromELFObject_aarch32(ObjectBuffer);
77bdd1243dSDimitry Andric   case ELF::EM_LOONGARCH:
78bdd1243dSDimitry Andric     return createLinkGraphFromELFObject_loongarch(ObjectBuffer);
79*06c3fb27SDimitry Andric   case ELF::EM_PPC64: {
80*06c3fb27SDimitry Andric     if (DataEncoding == ELF::ELFDATA2LSB)
81*06c3fb27SDimitry Andric       return createLinkGraphFromELFObject_ppc64le(ObjectBuffer);
82*06c3fb27SDimitry Andric     else
83*06c3fb27SDimitry Andric       return createLinkGraphFromELFObject_ppc64(ObjectBuffer);
84*06c3fb27SDimitry Andric   }
85fe6060f1SDimitry Andric   case ELF::EM_RISCV:
86fe6060f1SDimitry Andric     return createLinkGraphFromELFObject_riscv(ObjectBuffer);
87e8d8bef9SDimitry Andric   case ELF::EM_X86_64:
88fe6060f1SDimitry Andric     return createLinkGraphFromELFObject_x86_64(ObjectBuffer);
89bdd1243dSDimitry Andric   case ELF::EM_386:
90bdd1243dSDimitry Andric     return createLinkGraphFromELFObject_i386(ObjectBuffer);
91e8d8bef9SDimitry Andric   default:
92e8d8bef9SDimitry Andric     return make_error<JITLinkError>(
93e8d8bef9SDimitry Andric         "Unsupported target machine architecture in ELF object " +
94e8d8bef9SDimitry Andric         ObjectBuffer.getBufferIdentifier());
95e8d8bef9SDimitry Andric   }
96e8d8bef9SDimitry Andric }
97e8d8bef9SDimitry Andric 
98e8d8bef9SDimitry Andric void link_ELF(std::unique_ptr<LinkGraph> G,
99e8d8bef9SDimitry Andric               std::unique_ptr<JITLinkContext> Ctx) {
100e8d8bef9SDimitry Andric   switch (G->getTargetTriple().getArch()) {
101349cc55cSDimitry Andric   case Triple::aarch64:
102349cc55cSDimitry Andric     link_ELF_aarch64(std::move(G), std::move(Ctx));
103349cc55cSDimitry Andric     return;
104*06c3fb27SDimitry Andric   case Triple::arm:
105*06c3fb27SDimitry Andric   case Triple::armeb:
106*06c3fb27SDimitry Andric   case Triple::thumb:
107*06c3fb27SDimitry Andric   case Triple::thumbeb:
108*06c3fb27SDimitry Andric     link_ELF_aarch32(std::move(G), std::move(Ctx));
109*06c3fb27SDimitry Andric     return;
110bdd1243dSDimitry Andric   case Triple::loongarch32:
111bdd1243dSDimitry Andric   case Triple::loongarch64:
112bdd1243dSDimitry Andric     link_ELF_loongarch(std::move(G), std::move(Ctx));
113bdd1243dSDimitry Andric     return;
114*06c3fb27SDimitry Andric   case Triple::ppc64:
115*06c3fb27SDimitry Andric     link_ELF_ppc64(std::move(G), std::move(Ctx));
116*06c3fb27SDimitry Andric     return;
117*06c3fb27SDimitry Andric   case Triple::ppc64le:
118*06c3fb27SDimitry Andric     link_ELF_ppc64le(std::move(G), std::move(Ctx));
119*06c3fb27SDimitry Andric     return;
120fe6060f1SDimitry Andric   case Triple::riscv32:
121fe6060f1SDimitry Andric   case Triple::riscv64:
122fe6060f1SDimitry Andric     link_ELF_riscv(std::move(G), std::move(Ctx));
123fe6060f1SDimitry Andric     return;
124e8d8bef9SDimitry Andric   case Triple::x86_64:
125e8d8bef9SDimitry Andric     link_ELF_x86_64(std::move(G), std::move(Ctx));
126e8d8bef9SDimitry Andric     return;
127bdd1243dSDimitry Andric   case Triple::x86:
128bdd1243dSDimitry Andric     link_ELF_i386(std::move(G), std::move(Ctx));
129bdd1243dSDimitry Andric     return;
130e8d8bef9SDimitry Andric   default:
131e8d8bef9SDimitry Andric     Ctx->notifyFailed(make_error<JITLinkError>(
132e8d8bef9SDimitry Andric         "Unsupported target machine architecture in ELF link graph " +
133e8d8bef9SDimitry Andric         G->getName()));
1345ffd83dbSDimitry Andric     return;
1355ffd83dbSDimitry Andric   }
1365ffd83dbSDimitry Andric }
1375ffd83dbSDimitry Andric 
1385ffd83dbSDimitry Andric } // end namespace jitlink
1395ffd83dbSDimitry Andric } // end namespace llvm
140