xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //===-------------- ELF.cpp - JIT linker function for ELF -------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric //                     The LLVM Compiler Infrastructure
45ffd83dbSDimitry Andric //
55ffd83dbSDimitry Andric // This file is distributed under the University of Illinois Open Source
65ffd83dbSDimitry Andric // License. See LICENSE.TXT for details.
75ffd83dbSDimitry Andric //
85ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
95ffd83dbSDimitry Andric //
105ffd83dbSDimitry Andric // ELF jit-link function.
115ffd83dbSDimitry Andric //
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF.h"
155ffd83dbSDimitry Andric 
165ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
175ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
18*e8d8bef9SDimitry Andric #include "llvm/Object/ELF.h"
195ffd83dbSDimitry Andric #include "llvm/Support/Endian.h"
205ffd83dbSDimitry Andric #include "llvm/Support/Format.h"
215ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
225ffd83dbSDimitry Andric #include <cstring>
235ffd83dbSDimitry Andric 
245ffd83dbSDimitry Andric using namespace llvm;
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric #define DEBUG_TYPE "jitlink"
275ffd83dbSDimitry Andric 
285ffd83dbSDimitry Andric namespace llvm {
295ffd83dbSDimitry Andric namespace jitlink {
305ffd83dbSDimitry Andric 
31*e8d8bef9SDimitry Andric Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
32*e8d8bef9SDimitry Andric   const char *Data = Buffer.data();
335ffd83dbSDimitry Andric 
34*e8d8bef9SDimitry Andric   if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
35*e8d8bef9SDimitry Andric     if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
36*e8d8bef9SDimitry Andric       if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
37*e8d8bef9SDimitry Andric         return File->getHeader().e_machine;
38*e8d8bef9SDimitry Andric       } else {
39*e8d8bef9SDimitry Andric         return File.takeError();
40*e8d8bef9SDimitry Andric       }
41*e8d8bef9SDimitry Andric     } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
42*e8d8bef9SDimitry Andric       if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
43*e8d8bef9SDimitry Andric         return File->getHeader().e_machine;
44*e8d8bef9SDimitry Andric       } else {
45*e8d8bef9SDimitry Andric         return File.takeError();
46*e8d8bef9SDimitry Andric       }
47*e8d8bef9SDimitry Andric     }
48*e8d8bef9SDimitry Andric   }
495ffd83dbSDimitry Andric 
50*e8d8bef9SDimitry Andric   return ELF::EM_NONE;
51*e8d8bef9SDimitry Andric }
52*e8d8bef9SDimitry Andric 
53*e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>>
54*e8d8bef9SDimitry Andric createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
55*e8d8bef9SDimitry Andric   StringRef Buffer = ObjectBuffer.getBuffer();
56*e8d8bef9SDimitry Andric   if (Buffer.size() < ELF::EI_MAG3 + 1)
57*e8d8bef9SDimitry Andric     return make_error<JITLinkError>("Truncated ELF buffer");
58*e8d8bef9SDimitry Andric 
59*e8d8bef9SDimitry Andric   if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
60*e8d8bef9SDimitry Andric     return make_error<JITLinkError>("ELF magic not valid");
61*e8d8bef9SDimitry Andric 
62*e8d8bef9SDimitry Andric   Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
63*e8d8bef9SDimitry Andric   if (!TargetMachineArch)
64*e8d8bef9SDimitry Andric     return TargetMachineArch.takeError();
65*e8d8bef9SDimitry Andric 
66*e8d8bef9SDimitry Andric   switch (*TargetMachineArch) {
67*e8d8bef9SDimitry Andric   case ELF::EM_X86_64:
68*e8d8bef9SDimitry Andric     return createLinkGraphFromELFObject_x86_64(std::move(ObjectBuffer));
69*e8d8bef9SDimitry Andric   default:
70*e8d8bef9SDimitry Andric     return make_error<JITLinkError>(
71*e8d8bef9SDimitry Andric         "Unsupported target machine architecture in ELF object " +
72*e8d8bef9SDimitry Andric         ObjectBuffer.getBufferIdentifier());
73*e8d8bef9SDimitry Andric   }
74*e8d8bef9SDimitry Andric }
75*e8d8bef9SDimitry Andric 
76*e8d8bef9SDimitry Andric void link_ELF(std::unique_ptr<LinkGraph> G,
77*e8d8bef9SDimitry Andric               std::unique_ptr<JITLinkContext> Ctx) {
78*e8d8bef9SDimitry Andric   switch (G->getTargetTriple().getArch()) {
79*e8d8bef9SDimitry Andric   case Triple::x86_64:
80*e8d8bef9SDimitry Andric     link_ELF_x86_64(std::move(G), std::move(Ctx));
81*e8d8bef9SDimitry Andric     return;
82*e8d8bef9SDimitry Andric   default:
83*e8d8bef9SDimitry Andric     Ctx->notifyFailed(make_error<JITLinkError>(
84*e8d8bef9SDimitry Andric         "Unsupported target machine architecture in ELF link graph " +
85*e8d8bef9SDimitry Andric         G->getName()));
865ffd83dbSDimitry Andric     return;
875ffd83dbSDimitry Andric   }
885ffd83dbSDimitry Andric }
895ffd83dbSDimitry Andric 
905ffd83dbSDimitry Andric } // end namespace jitlink
915ffd83dbSDimitry Andric } // end namespace llvm
92