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 "llvm/Support/Endian.h"
25 #include "llvm/Support/Format.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include <cstring>
28 
29 using namespace llvm;
30 
31 #define DEBUG_TYPE "jitlink"
32 
33 namespace llvm {
34 namespace jitlink {
35 
36 Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
37   const char *Data = Buffer.data();
38 
39   if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
40     if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
41       if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
42         return File->getHeader().e_machine;
43       } else {
44         return File.takeError();
45       }
46     } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
47       if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
48         return File->getHeader().e_machine;
49       } else {
50         return File.takeError();
51       }
52     }
53   }
54 
55   return ELF::EM_NONE;
56 }
57 
58 Expected<std::unique_ptr<LinkGraph>>
59 createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
60   StringRef Buffer = ObjectBuffer.getBuffer();
61   if (Buffer.size() < ELF::EI_NIDENT)
62     return make_error<JITLinkError>("Truncated ELF buffer");
63 
64   if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
65     return make_error<JITLinkError>("ELF magic not valid");
66 
67   uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA];
68   Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
69   if (!TargetMachineArch)
70     return TargetMachineArch.takeError();
71 
72   switch (*TargetMachineArch) {
73   case ELF::EM_AARCH64:
74     return createLinkGraphFromELFObject_aarch64(ObjectBuffer);
75   case ELF::EM_ARM:
76     return createLinkGraphFromELFObject_aarch32(ObjectBuffer);
77   case ELF::EM_LOONGARCH:
78     return createLinkGraphFromELFObject_loongarch(ObjectBuffer);
79   case ELF::EM_PPC64: {
80     if (DataEncoding == ELF::ELFDATA2LSB)
81       return createLinkGraphFromELFObject_ppc64le(ObjectBuffer);
82     else
83       return createLinkGraphFromELFObject_ppc64(ObjectBuffer);
84   }
85   case ELF::EM_RISCV:
86     return createLinkGraphFromELFObject_riscv(ObjectBuffer);
87   case ELF::EM_X86_64:
88     return createLinkGraphFromELFObject_x86_64(ObjectBuffer);
89   case ELF::EM_386:
90     return createLinkGraphFromELFObject_i386(ObjectBuffer);
91   default:
92     return make_error<JITLinkError>(
93         "Unsupported target machine architecture in ELF object " +
94         ObjectBuffer.getBufferIdentifier());
95   }
96 }
97 
98 void link_ELF(std::unique_ptr<LinkGraph> G,
99               std::unique_ptr<JITLinkContext> Ctx) {
100   switch (G->getTargetTriple().getArch()) {
101   case Triple::aarch64:
102     link_ELF_aarch64(std::move(G), std::move(Ctx));
103     return;
104   case Triple::arm:
105   case Triple::armeb:
106   case Triple::thumb:
107   case Triple::thumbeb:
108     link_ELF_aarch32(std::move(G), std::move(Ctx));
109     return;
110   case Triple::loongarch32:
111   case Triple::loongarch64:
112     link_ELF_loongarch(std::move(G), std::move(Ctx));
113     return;
114   case Triple::ppc64:
115     link_ELF_ppc64(std::move(G), std::move(Ctx));
116     return;
117   case Triple::ppc64le:
118     link_ELF_ppc64le(std::move(G), std::move(Ctx));
119     return;
120   case Triple::riscv32:
121   case Triple::riscv64:
122     link_ELF_riscv(std::move(G), std::move(Ctx));
123     return;
124   case Triple::x86_64:
125     link_ELF_x86_64(std::move(G), std::move(Ctx));
126     return;
127   case Triple::x86:
128     link_ELF_i386(std::move(G), std::move(Ctx));
129     return;
130   default:
131     Ctx->notifyFailed(make_error<JITLinkError>(
132         "Unsupported target machine architecture in ELF link graph " +
133         G->getName()));
134     return;
135   }
136 }
137 
138 } // end namespace jitlink
139 } // end namespace llvm
140