1 //===-------------- ELF.cpp - JIT linker function for ELF -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // ELF jit-link function.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ExecutionEngine/JITLink/ELF.h"
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/Format.h"
25 #include "llvm/Support/MemoryBuffer.h"
30 #define DEBUG_TYPE "jitlink"
35 Expected
<uint16_t> readTargetMachineArch(StringRef Buffer
) {
36 const char *Data
= Buffer
.data();
38 if (Data
[ELF::EI_DATA
] == ELF::ELFDATA2LSB
) {
39 if (Data
[ELF::EI_CLASS
] == ELF::ELFCLASS64
) {
40 if (auto File
= llvm::object::ELF64LEFile::create(Buffer
)) {
41 return File
->getHeader().e_machine
;
43 return File
.takeError();
45 } else if (Data
[ELF::EI_CLASS
] == ELF::ELFCLASS32
) {
46 if (auto File
= llvm::object::ELF32LEFile::create(Buffer
)) {
47 return File
->getHeader().e_machine
;
49 return File
.takeError();
54 if (Data
[ELF::EI_DATA
] == ELF::ELFDATA2MSB
) {
55 if (Data
[ELF::EI_CLASS
] == ELF::ELFCLASS64
) {
56 if (auto File
= llvm::object::ELF64BEFile::create(Buffer
)) {
57 return File
->getHeader().e_machine
;
59 return File
.takeError();
61 } else if (Data
[ELF::EI_CLASS
] == ELF::ELFCLASS32
) {
62 if (auto File
= llvm::object::ELF32BEFile::create(Buffer
)) {
63 return File
->getHeader().e_machine
;
65 return File
.takeError();
73 Expected
<std::unique_ptr
<LinkGraph
>>
74 createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer
) {
75 StringRef Buffer
= ObjectBuffer
.getBuffer();
76 if (Buffer
.size() < ELF::EI_NIDENT
)
77 return make_error
<JITLinkError
>("Truncated ELF buffer");
79 if (memcmp(Buffer
.data(), ELF::ElfMagic
, strlen(ELF::ElfMagic
)) != 0)
80 return make_error
<JITLinkError
>("ELF magic not valid");
82 uint8_t DataEncoding
= Buffer
.data()[ELF::EI_DATA
];
83 Expected
<uint16_t> TargetMachineArch
= readTargetMachineArch(Buffer
);
84 if (!TargetMachineArch
)
85 return TargetMachineArch
.takeError();
87 switch (*TargetMachineArch
) {
89 return createLinkGraphFromELFObject_aarch64(ObjectBuffer
);
91 return createLinkGraphFromELFObject_aarch32(ObjectBuffer
);
92 case ELF::EM_LOONGARCH
:
93 return createLinkGraphFromELFObject_loongarch(ObjectBuffer
);
95 if (DataEncoding
== ELF::ELFDATA2LSB
)
96 return createLinkGraphFromELFObject_ppc64le(ObjectBuffer
);
98 return createLinkGraphFromELFObject_ppc64(ObjectBuffer
);
101 return createLinkGraphFromELFObject_riscv(ObjectBuffer
);
103 return createLinkGraphFromELFObject_x86_64(ObjectBuffer
);
105 return createLinkGraphFromELFObject_i386(ObjectBuffer
);
107 return make_error
<JITLinkError
>(
108 "Unsupported target machine architecture in ELF object " +
109 ObjectBuffer
.getBufferIdentifier());
113 void link_ELF(std::unique_ptr
<LinkGraph
> G
,
114 std::unique_ptr
<JITLinkContext
> Ctx
) {
115 switch (G
->getTargetTriple().getArch()) {
116 case Triple::aarch64
:
117 link_ELF_aarch64(std::move(G
), std::move(Ctx
));
122 case Triple::thumbeb
:
123 link_ELF_aarch32(std::move(G
), std::move(Ctx
));
125 case Triple::loongarch32
:
126 case Triple::loongarch64
:
127 link_ELF_loongarch(std::move(G
), std::move(Ctx
));
130 link_ELF_ppc64(std::move(G
), std::move(Ctx
));
132 case Triple::ppc64le
:
133 link_ELF_ppc64le(std::move(G
), std::move(Ctx
));
135 case Triple::riscv32
:
136 case Triple::riscv64
:
137 link_ELF_riscv(std::move(G
), std::move(Ctx
));
140 link_ELF_x86_64(std::move(G
), std::move(Ctx
));
143 link_ELF_i386(std::move(G
), std::move(Ctx
));
146 Ctx
->notifyFailed(make_error
<JITLinkError
>(
147 "Unsupported target machine architecture in ELF link graph " +
153 } // end namespace jitlink
154 } // end namespace llvm