xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp (revision 29fe204b4e87dcd78bebd40df512e8017dffea8f)
1 //===----- ELF_i386.cpp - JIT linker implementation for ELF/i386 ----===//
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/i386 jit-link implementation.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/ExecutionEngine/JITLink/ELF_i386.h"
14 #include "ELFLinkGraphBuilder.h"
15 #include "JITLinkGeneric.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/ExecutionEngine/JITLink/i386.h"
18 #include "llvm/Object/ELFObjectFile.h"
19 
20 #define DEBUG_TYPE "jitlink"
21 
22 using namespace llvm;
23 using namespace llvm::jitlink;
24 
25 namespace llvm {
26 namespace jitlink {
27 
28 class ELFJITLinker_i386 : public JITLinker<ELFJITLinker_i386> {
29   friend class JITLinker<ELFJITLinker_i386>;
30 
31 public:
32   ELFJITLinker_i386(std::unique_ptr<JITLinkContext> Ctx,
33                     std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
34       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
35 
36 private:
37   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
38     using namespace i386;
39     using namespace llvm::support;
40 
41     switch (E.getKind()) {
42     case i386::None: {
43       break;
44     }
45     }
46     return Error::success();
47   }
48 };
49 
50 template <typename ELFT>
51 class ELFLinkGraphBuilder_i386 : public ELFLinkGraphBuilder<ELFT> {
52 private:
53   static Expected<i386::EdgeKind_i386> getRelocationKind(const uint32_t Type) {
54     using namespace i386;
55     switch (Type) {
56     case ELF::R_386_NONE:
57       return EdgeKind_i386::None;
58     }
59 
60     return make_error<JITLinkError>("Unsupported i386 relocation:" +
61                                     formatv("{0:d}", Type));
62   }
63 
64   Error addRelocations() override {
65     LLVM_DEBUG(dbgs() << "Adding relocations\n");
66     using Base = ELFLinkGraphBuilder<ELFT>;
67 
68     return Error::success();
69   }
70 
71 public:
72   ELFLinkGraphBuilder_i386(StringRef FileName, const object::ELFFile<ELFT> &Obj,
73                            const Triple T)
74       : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
75                                   i386::getEdgeKindName) {}
76 };
77 
78 Expected<std::unique_ptr<LinkGraph>>
79 createLinkGraphFromELFObject_i386(MemoryBufferRef ObjectBuffer) {
80   LLVM_DEBUG({
81     dbgs() << "Building jitlink graph for new input "
82            << ObjectBuffer.getBufferIdentifier() << "...\n";
83   });
84 
85   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
86   if (!ELFObj)
87     return ELFObj.takeError();
88 
89   assert((*ELFObj)->getArch() == Triple::x86 &&
90          "Only i386 (little endian) is supported for now");
91 
92   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
93   return ELFLinkGraphBuilder_i386<object::ELF32LE>((*ELFObj)->getFileName(),
94                                                    ELFObjFile.getELFFile(),
95                                                    (*ELFObj)->makeTriple())
96       .buildGraph();
97 }
98 
99 void link_ELF_i386(std::unique_ptr<LinkGraph> G,
100                    std::unique_ptr<JITLinkContext> Ctx) {
101   PassConfiguration Config;
102   const Triple &TT = G->getTargetTriple();
103   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
104     if (auto MarkLive = Ctx->getMarkLivePass(TT))
105       Config.PrePrunePasses.push_back(std::move(MarkLive));
106     else
107       Config.PrePrunePasses.push_back(markAllSymbolsLive);
108   }
109   if (auto Err = Ctx->modifyPassConfig(*G, Config))
110     return Ctx->notifyFailed(std::move(Err));
111 
112   ELFJITLinker_i386::link(std::move(Ctx), std::move(G), std::move(Config));
113 }
114 
115 } // namespace jitlink
116 } // namespace llvm