xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF.cpp (revision 2ccf7ed277df28651b94bbee9fccefdf22fb074f)
12e40cf06SLang Hames //===-------------- ELF.cpp - JIT linker function for ELF -------------===//
22e40cf06SLang Hames //
3c874dd53SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c874dd53SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
5c874dd53SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62e40cf06SLang Hames //
72e40cf06SLang Hames //===----------------------------------------------------------------------===//
82e40cf06SLang Hames //
92e40cf06SLang Hames // ELF jit-link function.
102e40cf06SLang Hames //
112e40cf06SLang Hames //===----------------------------------------------------------------------===//
122e40cf06SLang Hames 
132e40cf06SLang Hames #include "llvm/ExecutionEngine/JITLink/ELF.h"
142e40cf06SLang Hames 
152e40cf06SLang Hames #include "llvm/BinaryFormat/ELF.h"
165c1d160cSStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h"
172ed91da0SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h"
1829fe204bSKshitij Jain #include "llvm/ExecutionEngine/JITLink/ELF_i386.h"
19f10d452dSwanglei #include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h"
208313507aSLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h"
210ad562b4Sluxufan #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
222e40cf06SLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
2383b52b5bSStefan Gränitz #include "llvm/Object/ELF.h"
242e40cf06SLang Hames #include <cstring>
252e40cf06SLang Hames 
262e40cf06SLang Hames using namespace llvm;
272e40cf06SLang Hames 
282e40cf06SLang Hames #define DEBUG_TYPE "jitlink"
292e40cf06SLang Hames 
302e40cf06SLang Hames namespace llvm {
312e40cf06SLang Hames namespace jitlink {
322e40cf06SLang Hames 
3383b52b5bSStefan Gränitz Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
3483b52b5bSStefan Gränitz   const char *Data = Buffer.data();
3583b52b5bSStefan Gränitz 
3683b52b5bSStefan Gränitz   if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
3783b52b5bSStefan Gränitz     if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
3883b52b5bSStefan Gränitz       if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
3983b52b5bSStefan Gränitz         return File->getHeader().e_machine;
4083b52b5bSStefan Gränitz       } else {
4183b52b5bSStefan Gränitz         return File.takeError();
4283b52b5bSStefan Gränitz       }
4383b52b5bSStefan Gränitz     } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
4483b52b5bSStefan Gränitz       if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
4583b52b5bSStefan Gränitz         return File->getHeader().e_machine;
4683b52b5bSStefan Gränitz       } else {
4783b52b5bSStefan Gränitz         return File.takeError();
4883b52b5bSStefan Gränitz       }
4983b52b5bSStefan Gränitz     }
5083b52b5bSStefan Gränitz   }
5183b52b5bSStefan Gränitz 
52be7a5465SKai Luo   if (Data[ELF::EI_DATA] == ELF::ELFDATA2MSB) {
53be7a5465SKai Luo     if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
54be7a5465SKai Luo       if (auto File = llvm::object::ELF64BEFile::create(Buffer)) {
55be7a5465SKai Luo         return File->getHeader().e_machine;
56be7a5465SKai Luo       } else {
57be7a5465SKai Luo         return File.takeError();
58be7a5465SKai Luo       }
59be7a5465SKai Luo     } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
60be7a5465SKai Luo       if (auto File = llvm::object::ELF32BEFile::create(Buffer)) {
61be7a5465SKai Luo         return File->getHeader().e_machine;
62be7a5465SKai Luo       } else {
63be7a5465SKai Luo         return File.takeError();
64be7a5465SKai Luo       }
65be7a5465SKai Luo     }
66be7a5465SKai Luo   }
67be7a5465SKai Luo 
6883b52b5bSStefan Gränitz   return ELF::EM_NONE;
6983b52b5bSStefan Gränitz }
7083b52b5bSStefan Gränitz 
71ec6b71dfSLang Hames Expected<std::unique_ptr<LinkGraph>>
72*2ccf7ed2SJared Wyles createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer,
73*2ccf7ed2SJared Wyles                              std::shared_ptr<orc::SymbolStringPool> SSP) {
74ec6b71dfSLang Hames   StringRef Buffer = ObjectBuffer.getBuffer();
75d8472ac2SLang Hames   if (Buffer.size() < ELF::EI_NIDENT)
76ec6b71dfSLang Hames     return make_error<JITLinkError>("Truncated ELF buffer");
772e40cf06SLang Hames 
78ec6b71dfSLang Hames   if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
79ec6b71dfSLang Hames     return make_error<JITLinkError>("ELF magic not valid");
802e40cf06SLang Hames 
818313507aSLang Hames   uint8_t DataEncoding = Buffer.data()[ELF::EI_DATA];
8283b52b5bSStefan Gränitz   Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
83ec6b71dfSLang Hames   if (!TargetMachineArch)
84ec6b71dfSLang Hames     return TargetMachineArch.takeError();
8583b52b5bSStefan Gränitz 
8683b52b5bSStefan Gränitz   switch (*TargetMachineArch) {
872ed91da0SStefan Gränitz   case ELF::EM_AARCH64:
88*2ccf7ed2SJared Wyles     return createLinkGraphFromELFObject_aarch64(ObjectBuffer, std::move(SSP));
895c1d160cSStefan Gränitz   case ELF::EM_ARM:
90*2ccf7ed2SJared Wyles     return createLinkGraphFromELFObject_aarch32(ObjectBuffer, std::move(SSP));
918313507aSLang Hames   case ELF::EM_PPC64: {
928313507aSLang Hames     if (DataEncoding == ELF::ELFDATA2LSB)
93*2ccf7ed2SJared Wyles       return createLinkGraphFromELFObject_ppc64le(ObjectBuffer, std::move(SSP));
948313507aSLang Hames     else
95*2ccf7ed2SJared Wyles       return createLinkGraphFromELFObject_ppc64(ObjectBuffer, std::move(SSP));
968313507aSLang Hames   }
97*2ccf7ed2SJared Wyles   case ELF::EM_LOONGARCH:
98*2ccf7ed2SJared Wyles     return createLinkGraphFromELFObject_loongarch(ObjectBuffer, std::move(SSP));
990ad562b4Sluxufan   case ELF::EM_RISCV:
100*2ccf7ed2SJared Wyles     return createLinkGraphFromELFObject_riscv(ObjectBuffer, std::move(SSP));
10183b52b5bSStefan Gränitz   case ELF::EM_X86_64:
102*2ccf7ed2SJared Wyles     return createLinkGraphFromELFObject_x86_64(ObjectBuffer, std::move(SSP));
10329fe204bSKshitij Jain   case ELF::EM_386:
104*2ccf7ed2SJared Wyles     return createLinkGraphFromELFObject_i386(ObjectBuffer, std::move(SSP));
105ec6b71dfSLang Hames   default:
106ec6b71dfSLang Hames     return make_error<JITLinkError>(
107ec6b71dfSLang Hames         "Unsupported target machine architecture in ELF object " +
108ec6b71dfSLang Hames         ObjectBuffer.getBufferIdentifier());
109ec6b71dfSLang Hames   }
110ec6b71dfSLang Hames }
111ec6b71dfSLang Hames 
112ec6b71dfSLang Hames void link_ELF(std::unique_ptr<LinkGraph> G,
113ec6b71dfSLang Hames               std::unique_ptr<JITLinkContext> Ctx) {
114ec6b71dfSLang Hames   switch (G->getTargetTriple().getArch()) {
1152ed91da0SStefan Gränitz   case Triple::aarch64:
1162ed91da0SStefan Gränitz     link_ELF_aarch64(std::move(G), std::move(Ctx));
1172ed91da0SStefan Gränitz     return;
1185c1d160cSStefan Gränitz   case Triple::arm:
1195c1d160cSStefan Gränitz   case Triple::armeb:
1205c1d160cSStefan Gränitz   case Triple::thumb:
1215c1d160cSStefan Gränitz   case Triple::thumbeb:
1225c1d160cSStefan Gränitz     link_ELF_aarch32(std::move(G), std::move(Ctx));
1235c1d160cSStefan Gränitz     return;
124f10d452dSwanglei   case Triple::loongarch32:
125f10d452dSwanglei   case Triple::loongarch64:
126f10d452dSwanglei     link_ELF_loongarch(std::move(G), std::move(Ctx));
127f10d452dSwanglei     return;
1288313507aSLang Hames   case Triple::ppc64:
1298313507aSLang Hames     link_ELF_ppc64(std::move(G), std::move(Ctx));
1308313507aSLang Hames     return;
1318313507aSLang Hames   case Triple::ppc64le:
1328313507aSLang Hames     link_ELF_ppc64le(std::move(G), std::move(Ctx));
1338313507aSLang Hames     return;
1340ad562b4Sluxufan   case Triple::riscv32:
1350ad562b4Sluxufan   case Triple::riscv64:
1360ad562b4Sluxufan     link_ELF_riscv(std::move(G), std::move(Ctx));
1370ad562b4Sluxufan     return;
138ec6b71dfSLang Hames   case Triple::x86_64:
139ec6b71dfSLang Hames     link_ELF_x86_64(std::move(G), std::move(Ctx));
14083b52b5bSStefan Gränitz     return;
14129fe204bSKshitij Jain   case Triple::x86:
14229fe204bSKshitij Jain     link_ELF_i386(std::move(G), std::move(Ctx));
14329fe204bSKshitij Jain     return;
14483b52b5bSStefan Gränitz   default:
14583b52b5bSStefan Gränitz     Ctx->notifyFailed(make_error<JITLinkError>(
146ec6b71dfSLang Hames         "Unsupported target machine architecture in ELF link graph " +
147ec6b71dfSLang Hames         G->getName()));
14883b52b5bSStefan Gränitz     return;
14983b52b5bSStefan Gränitz   }
1502e40cf06SLang Hames }
1512e40cf06SLang Hames 
1522e40cf06SLang Hames } // end namespace jitlink
1532e40cf06SLang Hames } // end namespace llvm
154