xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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"
1606c3fb27SDimitry 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"
2006c3fb27SDimitry 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/Format.h"
255ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
265ffd83dbSDimitry Andric #include <cstring>
275ffd83dbSDimitry Andric 
285ffd83dbSDimitry Andric using namespace llvm;
295ffd83dbSDimitry Andric 
305ffd83dbSDimitry Andric #define DEBUG_TYPE "jitlink"
315ffd83dbSDimitry Andric 
325ffd83dbSDimitry Andric namespace llvm {
335ffd83dbSDimitry Andric namespace jitlink {
345ffd83dbSDimitry Andric 
35e8d8bef9SDimitry Andric Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
36e8d8bef9SDimitry Andric   const char *Data = Buffer.data();
375ffd83dbSDimitry Andric 
38e8d8bef9SDimitry Andric   if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
39e8d8bef9SDimitry Andric     if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
40e8d8bef9SDimitry Andric       if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
41e8d8bef9SDimitry Andric         return File->getHeader().e_machine;
42e8d8bef9SDimitry Andric       } else {
43e8d8bef9SDimitry Andric         return File.takeError();
44e8d8bef9SDimitry Andric       }
45e8d8bef9SDimitry Andric     } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
46e8d8bef9SDimitry Andric       if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
47e8d8bef9SDimitry Andric         return File->getHeader().e_machine;
48e8d8bef9SDimitry Andric       } else {
49e8d8bef9SDimitry Andric         return File.takeError();
50e8d8bef9SDimitry Andric       }
51e8d8bef9SDimitry Andric     }
52e8d8bef9SDimitry Andric   }
535ffd83dbSDimitry Andric 
54*5f757f3fSDimitry Andric   if (Data[ELF::EI_DATA] == ELF::ELFDATA2MSB) {
55*5f757f3fSDimitry Andric     if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
56*5f757f3fSDimitry Andric       if (auto File = llvm::object::ELF64BEFile::create(Buffer)) {
57*5f757f3fSDimitry Andric         return File->getHeader().e_machine;
58*5f757f3fSDimitry Andric       } else {
59*5f757f3fSDimitry Andric         return File.takeError();
60*5f757f3fSDimitry Andric       }
61*5f757f3fSDimitry Andric     } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
62*5f757f3fSDimitry Andric       if (auto File = llvm::object::ELF32BEFile::create(Buffer)) {
63*5f757f3fSDimitry Andric         return File->getHeader().e_machine;
64*5f757f3fSDimitry Andric       } else {
65*5f757f3fSDimitry Andric         return File.takeError();
66*5f757f3fSDimitry Andric       }
67*5f757f3fSDimitry Andric     }
68*5f757f3fSDimitry Andric   }
69*5f757f3fSDimitry Andric 
70e8d8bef9SDimitry Andric   return ELF::EM_NONE;
71e8d8bef9SDimitry Andric }
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>>
74e8d8bef9SDimitry Andric createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
75e8d8bef9SDimitry Andric   StringRef Buffer = ObjectBuffer.getBuffer();
7606c3fb27SDimitry Andric   if (Buffer.size() < ELF::EI_NIDENT)
77e8d8bef9SDimitry Andric     return make_error<JITLinkError>("Truncated ELF buffer");
78e8d8bef9SDimitry Andric 
79e8d8bef9SDimitry Andric   if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
80e8d8bef9SDimitry Andric     return make_error<JITLinkError>("ELF magic not valid");
81e8d8bef9SDimitry Andric 
8206c3fb27SDimitry Andric   uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA];
83e8d8bef9SDimitry Andric   Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
84e8d8bef9SDimitry Andric   if (!TargetMachineArch)
85e8d8bef9SDimitry Andric     return TargetMachineArch.takeError();
86e8d8bef9SDimitry Andric 
87e8d8bef9SDimitry Andric   switch (*TargetMachineArch) {
88349cc55cSDimitry Andric   case ELF::EM_AARCH64:
89349cc55cSDimitry Andric     return createLinkGraphFromELFObject_aarch64(ObjectBuffer);
9006c3fb27SDimitry Andric   case ELF::EM_ARM:
9106c3fb27SDimitry Andric     return createLinkGraphFromELFObject_aarch32(ObjectBuffer);
92bdd1243dSDimitry Andric   case ELF::EM_LOONGARCH:
93bdd1243dSDimitry Andric     return createLinkGraphFromELFObject_loongarch(ObjectBuffer);
9406c3fb27SDimitry Andric   case ELF::EM_PPC64: {
9506c3fb27SDimitry Andric     if (DataEncoding == ELF::ELFDATA2LSB)
9606c3fb27SDimitry Andric       return createLinkGraphFromELFObject_ppc64le(ObjectBuffer);
9706c3fb27SDimitry Andric     else
9806c3fb27SDimitry Andric       return createLinkGraphFromELFObject_ppc64(ObjectBuffer);
9906c3fb27SDimitry Andric   }
100fe6060f1SDimitry Andric   case ELF::EM_RISCV:
101fe6060f1SDimitry Andric     return createLinkGraphFromELFObject_riscv(ObjectBuffer);
102e8d8bef9SDimitry Andric   case ELF::EM_X86_64:
103fe6060f1SDimitry Andric     return createLinkGraphFromELFObject_x86_64(ObjectBuffer);
104bdd1243dSDimitry Andric   case ELF::EM_386:
105bdd1243dSDimitry Andric     return createLinkGraphFromELFObject_i386(ObjectBuffer);
106e8d8bef9SDimitry Andric   default:
107e8d8bef9SDimitry Andric     return make_error<JITLinkError>(
108e8d8bef9SDimitry Andric         "Unsupported target machine architecture in ELF object " +
109e8d8bef9SDimitry Andric         ObjectBuffer.getBufferIdentifier());
110e8d8bef9SDimitry Andric   }
111e8d8bef9SDimitry Andric }
112e8d8bef9SDimitry Andric 
113e8d8bef9SDimitry Andric void link_ELF(std::unique_ptr<LinkGraph> G,
114e8d8bef9SDimitry Andric               std::unique_ptr<JITLinkContext> Ctx) {
115e8d8bef9SDimitry Andric   switch (G->getTargetTriple().getArch()) {
116349cc55cSDimitry Andric   case Triple::aarch64:
117349cc55cSDimitry Andric     link_ELF_aarch64(std::move(G), std::move(Ctx));
118349cc55cSDimitry Andric     return;
11906c3fb27SDimitry Andric   case Triple::arm:
12006c3fb27SDimitry Andric   case Triple::armeb:
12106c3fb27SDimitry Andric   case Triple::thumb:
12206c3fb27SDimitry Andric   case Triple::thumbeb:
12306c3fb27SDimitry Andric     link_ELF_aarch32(std::move(G), std::move(Ctx));
12406c3fb27SDimitry Andric     return;
125bdd1243dSDimitry Andric   case Triple::loongarch32:
126bdd1243dSDimitry Andric   case Triple::loongarch64:
127bdd1243dSDimitry Andric     link_ELF_loongarch(std::move(G), std::move(Ctx));
128bdd1243dSDimitry Andric     return;
12906c3fb27SDimitry Andric   case Triple::ppc64:
13006c3fb27SDimitry Andric     link_ELF_ppc64(std::move(G), std::move(Ctx));
13106c3fb27SDimitry Andric     return;
13206c3fb27SDimitry Andric   case Triple::ppc64le:
13306c3fb27SDimitry Andric     link_ELF_ppc64le(std::move(G), std::move(Ctx));
13406c3fb27SDimitry Andric     return;
135fe6060f1SDimitry Andric   case Triple::riscv32:
136fe6060f1SDimitry Andric   case Triple::riscv64:
137fe6060f1SDimitry Andric     link_ELF_riscv(std::move(G), std::move(Ctx));
138fe6060f1SDimitry Andric     return;
139e8d8bef9SDimitry Andric   case Triple::x86_64:
140e8d8bef9SDimitry Andric     link_ELF_x86_64(std::move(G), std::move(Ctx));
141e8d8bef9SDimitry Andric     return;
142bdd1243dSDimitry Andric   case Triple::x86:
143bdd1243dSDimitry Andric     link_ELF_i386(std::move(G), std::move(Ctx));
144bdd1243dSDimitry Andric     return;
145e8d8bef9SDimitry Andric   default:
146e8d8bef9SDimitry Andric     Ctx->notifyFailed(make_error<JITLinkError>(
147e8d8bef9SDimitry Andric         "Unsupported target machine architecture in ELF link graph " +
148e8d8bef9SDimitry Andric         G->getName()));
1495ffd83dbSDimitry Andric     return;
1505ffd83dbSDimitry Andric   }
1515ffd83dbSDimitry Andric }
1525ffd83dbSDimitry Andric 
1535ffd83dbSDimitry Andric } // end namespace jitlink
1545ffd83dbSDimitry Andric } // end namespace llvm
155