xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1*bdd1243dSDimitry Andric //===----- ELF_i386.cpp - JIT linker implementation for ELF/i386 ----===//
2*bdd1243dSDimitry Andric //
3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bdd1243dSDimitry Andric //
7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8*bdd1243dSDimitry Andric //
9*bdd1243dSDimitry Andric // ELF/i386 jit-link implementation.
10*bdd1243dSDimitry Andric //
11*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12*bdd1243dSDimitry Andric 
13*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_i386.h"
14*bdd1243dSDimitry Andric #include "DefineExternalSectionStartAndEndSymbols.h"
15*bdd1243dSDimitry Andric #include "ELFLinkGraphBuilder.h"
16*bdd1243dSDimitry Andric #include "JITLinkGeneric.h"
17*bdd1243dSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
18*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/i386.h"
19*bdd1243dSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
20*bdd1243dSDimitry Andric 
21*bdd1243dSDimitry Andric #define DEBUG_TYPE "jitlink"
22*bdd1243dSDimitry Andric 
23*bdd1243dSDimitry Andric using namespace llvm;
24*bdd1243dSDimitry Andric using namespace llvm::jitlink;
25*bdd1243dSDimitry Andric 
26*bdd1243dSDimitry Andric namespace {
27*bdd1243dSDimitry Andric constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
28*bdd1243dSDimitry Andric 
29*bdd1243dSDimitry Andric Error buildTables_ELF_i386(LinkGraph &G) {
30*bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
31*bdd1243dSDimitry Andric 
32*bdd1243dSDimitry Andric   i386::GOTTableManager GOT;
33*bdd1243dSDimitry Andric   visitExistingEdges(G, GOT);
34*bdd1243dSDimitry Andric   return Error::success();
35*bdd1243dSDimitry Andric }
36*bdd1243dSDimitry Andric } // namespace
37*bdd1243dSDimitry Andric 
38*bdd1243dSDimitry Andric namespace llvm::jitlink {
39*bdd1243dSDimitry Andric 
40*bdd1243dSDimitry Andric class ELFJITLinker_i386 : public JITLinker<ELFJITLinker_i386> {
41*bdd1243dSDimitry Andric   friend class JITLinker<ELFJITLinker_i386>;
42*bdd1243dSDimitry Andric 
43*bdd1243dSDimitry Andric public:
44*bdd1243dSDimitry Andric   ELFJITLinker_i386(std::unique_ptr<JITLinkContext> Ctx,
45*bdd1243dSDimitry Andric                     std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
46*bdd1243dSDimitry Andric       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
47*bdd1243dSDimitry Andric     getPassConfig().PostAllocationPasses.push_back(
48*bdd1243dSDimitry Andric         [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });
49*bdd1243dSDimitry Andric   }
50*bdd1243dSDimitry Andric 
51*bdd1243dSDimitry Andric private:
52*bdd1243dSDimitry Andric   Symbol *GOTSymbol = nullptr;
53*bdd1243dSDimitry Andric 
54*bdd1243dSDimitry Andric   Error getOrCreateGOTSymbol(LinkGraph &G) {
55*bdd1243dSDimitry Andric     auto DefineExternalGOTSymbolIfPresent =
56*bdd1243dSDimitry Andric         createDefineExternalSectionStartAndEndSymbolsPass(
57*bdd1243dSDimitry Andric             [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
58*bdd1243dSDimitry Andric               if (Sym.getName() == ELFGOTSymbolName)
59*bdd1243dSDimitry Andric                 if (auto *GOTSection = G.findSectionByName(
60*bdd1243dSDimitry Andric                         i386::GOTTableManager::getSectionName())) {
61*bdd1243dSDimitry Andric                   GOTSymbol = &Sym;
62*bdd1243dSDimitry Andric                   return {*GOTSection, true};
63*bdd1243dSDimitry Andric                 }
64*bdd1243dSDimitry Andric               return {};
65*bdd1243dSDimitry Andric             });
66*bdd1243dSDimitry Andric 
67*bdd1243dSDimitry Andric     // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an
68*bdd1243dSDimitry Andric     // external.
69*bdd1243dSDimitry Andric     if (auto Err = DefineExternalGOTSymbolIfPresent(G))
70*bdd1243dSDimitry Andric       return Err;
71*bdd1243dSDimitry Andric 
72*bdd1243dSDimitry Andric     // If we succeeded then we're done.
73*bdd1243dSDimitry Andric     if (GOTSymbol)
74*bdd1243dSDimitry Andric       return Error::success();
75*bdd1243dSDimitry Andric 
76*bdd1243dSDimitry Andric     // Otherwise look for a GOT section: If it already has a start symbol we'll
77*bdd1243dSDimitry Andric     // record it, otherwise we'll create our own.
78*bdd1243dSDimitry Andric     // If there's a GOT section but we didn't find an external GOT symbol...
79*bdd1243dSDimitry Andric     if (auto *GOTSection =
80*bdd1243dSDimitry Andric             G.findSectionByName(i386::GOTTableManager::getSectionName())) {
81*bdd1243dSDimitry Andric 
82*bdd1243dSDimitry Andric       // Check for an existing defined symbol.
83*bdd1243dSDimitry Andric       for (auto *Sym : GOTSection->symbols())
84*bdd1243dSDimitry Andric         if (Sym->getName() == ELFGOTSymbolName) {
85*bdd1243dSDimitry Andric           GOTSymbol = Sym;
86*bdd1243dSDimitry Andric           return Error::success();
87*bdd1243dSDimitry Andric         }
88*bdd1243dSDimitry Andric 
89*bdd1243dSDimitry Andric       // If there's no defined symbol then create one.
90*bdd1243dSDimitry Andric       SectionRange SR(*GOTSection);
91*bdd1243dSDimitry Andric 
92*bdd1243dSDimitry Andric       if (SR.empty()) {
93*bdd1243dSDimitry Andric         GOTSymbol =
94*bdd1243dSDimitry Andric             &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0,
95*bdd1243dSDimitry Andric                                  Linkage::Strong, Scope::Local, true);
96*bdd1243dSDimitry Andric       } else {
97*bdd1243dSDimitry Andric         GOTSymbol =
98*bdd1243dSDimitry Andric             &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0,
99*bdd1243dSDimitry Andric                                 Linkage::Strong, Scope::Local, false, true);
100*bdd1243dSDimitry Andric       }
101*bdd1243dSDimitry Andric     }
102*bdd1243dSDimitry Andric 
103*bdd1243dSDimitry Andric     return Error::success();
104*bdd1243dSDimitry Andric   }
105*bdd1243dSDimitry Andric 
106*bdd1243dSDimitry Andric   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
107*bdd1243dSDimitry Andric     return i386::applyFixup(G, B, E, GOTSymbol);
108*bdd1243dSDimitry Andric   }
109*bdd1243dSDimitry Andric };
110*bdd1243dSDimitry Andric 
111*bdd1243dSDimitry Andric template <typename ELFT>
112*bdd1243dSDimitry Andric class ELFLinkGraphBuilder_i386 : public ELFLinkGraphBuilder<ELFT> {
113*bdd1243dSDimitry Andric private:
114*bdd1243dSDimitry Andric   static Expected<i386::EdgeKind_i386> getRelocationKind(const uint32_t Type) {
115*bdd1243dSDimitry Andric     using namespace i386;
116*bdd1243dSDimitry Andric     switch (Type) {
117*bdd1243dSDimitry Andric     case ELF::R_386_NONE:
118*bdd1243dSDimitry Andric       return EdgeKind_i386::None;
119*bdd1243dSDimitry Andric     case ELF::R_386_32:
120*bdd1243dSDimitry Andric       return EdgeKind_i386::Pointer32;
121*bdd1243dSDimitry Andric     case ELF::R_386_PC32:
122*bdd1243dSDimitry Andric       return EdgeKind_i386::PCRel32;
123*bdd1243dSDimitry Andric     case ELF::R_386_16:
124*bdd1243dSDimitry Andric       return EdgeKind_i386::Pointer16;
125*bdd1243dSDimitry Andric     case ELF::R_386_PC16:
126*bdd1243dSDimitry Andric       return EdgeKind_i386::PCRel16;
127*bdd1243dSDimitry Andric     case ELF::R_386_GOT32:
128*bdd1243dSDimitry Andric       return EdgeKind_i386::RequestGOTAndTransformToDelta32FromGOT;
129*bdd1243dSDimitry Andric     case ELF::R_386_GOTPC:
130*bdd1243dSDimitry Andric       return EdgeKind_i386::Delta32;
131*bdd1243dSDimitry Andric     case ELF::R_386_GOTOFF:
132*bdd1243dSDimitry Andric       return EdgeKind_i386::Delta32FromGOT;
133*bdd1243dSDimitry Andric     }
134*bdd1243dSDimitry Andric 
135*bdd1243dSDimitry Andric     return make_error<JITLinkError>("Unsupported i386 relocation:" +
136*bdd1243dSDimitry Andric                                     formatv("{0:d}", Type));
137*bdd1243dSDimitry Andric   }
138*bdd1243dSDimitry Andric 
139*bdd1243dSDimitry Andric   Error addRelocations() override {
140*bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "Adding relocations\n");
141*bdd1243dSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
142*bdd1243dSDimitry Andric     using Self = ELFLinkGraphBuilder_i386;
143*bdd1243dSDimitry Andric 
144*bdd1243dSDimitry Andric     for (const auto &RelSect : Base::Sections) {
145*bdd1243dSDimitry Andric       // Validate the section to read relocation entries from.
146*bdd1243dSDimitry Andric       if (RelSect.sh_type == ELF::SHT_RELA)
147*bdd1243dSDimitry Andric         return make_error<StringError>(
148*bdd1243dSDimitry Andric             "No SHT_RELA in valid i386 ELF object files",
149*bdd1243dSDimitry Andric             inconvertibleErrorCode());
150*bdd1243dSDimitry Andric 
151*bdd1243dSDimitry Andric       if (Error Err = Base::forEachRelRelocation(RelSect, this,
152*bdd1243dSDimitry Andric                                                  &Self::addSingleRelocation))
153*bdd1243dSDimitry Andric         return Err;
154*bdd1243dSDimitry Andric     }
155*bdd1243dSDimitry Andric 
156*bdd1243dSDimitry Andric     return Error::success();
157*bdd1243dSDimitry Andric   }
158*bdd1243dSDimitry Andric 
159*bdd1243dSDimitry Andric   Error addSingleRelocation(const typename ELFT::Rel &Rel,
160*bdd1243dSDimitry Andric                             const typename ELFT::Shdr &FixupSection,
161*bdd1243dSDimitry Andric                             Block &BlockToFix) {
162*bdd1243dSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
163*bdd1243dSDimitry Andric 
164*bdd1243dSDimitry Andric     uint32_t SymbolIndex = Rel.getSymbol(false);
165*bdd1243dSDimitry Andric     auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
166*bdd1243dSDimitry Andric     if (!ObjSymbol)
167*bdd1243dSDimitry Andric       return ObjSymbol.takeError();
168*bdd1243dSDimitry Andric 
169*bdd1243dSDimitry Andric     Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
170*bdd1243dSDimitry Andric     if (!GraphSymbol)
171*bdd1243dSDimitry Andric       return make_error<StringError>(
172*bdd1243dSDimitry Andric           formatv("Could not find symbol at given index, did you add it to "
173*bdd1243dSDimitry Andric                   "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
174*bdd1243dSDimitry Andric                   SymbolIndex, (*ObjSymbol)->st_shndx,
175*bdd1243dSDimitry Andric                   Base::GraphSymbols.size()),
176*bdd1243dSDimitry Andric           inconvertibleErrorCode());
177*bdd1243dSDimitry Andric 
178*bdd1243dSDimitry Andric     Expected<i386::EdgeKind_i386> Kind = getRelocationKind(Rel.getType(false));
179*bdd1243dSDimitry Andric     if (!Kind)
180*bdd1243dSDimitry Andric       return Kind.takeError();
181*bdd1243dSDimitry Andric 
182*bdd1243dSDimitry Andric     auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset;
183*bdd1243dSDimitry Andric     int64_t Addend = 0;
184*bdd1243dSDimitry Andric 
185*bdd1243dSDimitry Andric     switch (*Kind) {
186*bdd1243dSDimitry Andric     case i386::EdgeKind_i386::Delta32: {
187*bdd1243dSDimitry Andric       const char *FixupContent = BlockToFix.getContent().data() +
188*bdd1243dSDimitry Andric                                  (FixupAddress - BlockToFix.getAddress());
189*bdd1243dSDimitry Andric       Addend = *(const support::ulittle32_t *)FixupContent;
190*bdd1243dSDimitry Andric       break;
191*bdd1243dSDimitry Andric     }
192*bdd1243dSDimitry Andric     default:
193*bdd1243dSDimitry Andric       break;
194*bdd1243dSDimitry Andric     }
195*bdd1243dSDimitry Andric 
196*bdd1243dSDimitry Andric     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
197*bdd1243dSDimitry Andric     Edge GE(*Kind, Offset, *GraphSymbol, Addend);
198*bdd1243dSDimitry Andric     LLVM_DEBUG({
199*bdd1243dSDimitry Andric       dbgs() << "    ";
200*bdd1243dSDimitry Andric       printEdge(dbgs(), BlockToFix, GE, i386::getEdgeKindName(*Kind));
201*bdd1243dSDimitry Andric       dbgs() << "\n";
202*bdd1243dSDimitry Andric     });
203*bdd1243dSDimitry Andric 
204*bdd1243dSDimitry Andric     BlockToFix.addEdge(std::move(GE));
205*bdd1243dSDimitry Andric     return Error::success();
206*bdd1243dSDimitry Andric   }
207*bdd1243dSDimitry Andric 
208*bdd1243dSDimitry Andric public:
209*bdd1243dSDimitry Andric   ELFLinkGraphBuilder_i386(StringRef FileName, const object::ELFFile<ELFT> &Obj,
210*bdd1243dSDimitry Andric                            const Triple T)
211*bdd1243dSDimitry Andric       : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
212*bdd1243dSDimitry Andric                                   i386::getEdgeKindName) {}
213*bdd1243dSDimitry Andric };
214*bdd1243dSDimitry Andric 
215*bdd1243dSDimitry Andric Expected<std::unique_ptr<LinkGraph>>
216*bdd1243dSDimitry Andric createLinkGraphFromELFObject_i386(MemoryBufferRef ObjectBuffer) {
217*bdd1243dSDimitry Andric   LLVM_DEBUG({
218*bdd1243dSDimitry Andric     dbgs() << "Building jitlink graph for new input "
219*bdd1243dSDimitry Andric            << ObjectBuffer.getBufferIdentifier() << "...\n";
220*bdd1243dSDimitry Andric   });
221*bdd1243dSDimitry Andric 
222*bdd1243dSDimitry Andric   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
223*bdd1243dSDimitry Andric   if (!ELFObj)
224*bdd1243dSDimitry Andric     return ELFObj.takeError();
225*bdd1243dSDimitry Andric 
226*bdd1243dSDimitry Andric   assert((*ELFObj)->getArch() == Triple::x86 &&
227*bdd1243dSDimitry Andric          "Only i386 (little endian) is supported for now");
228*bdd1243dSDimitry Andric 
229*bdd1243dSDimitry Andric   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
230*bdd1243dSDimitry Andric   return ELFLinkGraphBuilder_i386<object::ELF32LE>((*ELFObj)->getFileName(),
231*bdd1243dSDimitry Andric                                                    ELFObjFile.getELFFile(),
232*bdd1243dSDimitry Andric                                                    (*ELFObj)->makeTriple())
233*bdd1243dSDimitry Andric       .buildGraph();
234*bdd1243dSDimitry Andric }
235*bdd1243dSDimitry Andric 
236*bdd1243dSDimitry Andric void link_ELF_i386(std::unique_ptr<LinkGraph> G,
237*bdd1243dSDimitry Andric                    std::unique_ptr<JITLinkContext> Ctx) {
238*bdd1243dSDimitry Andric   PassConfiguration Config;
239*bdd1243dSDimitry Andric   const Triple &TT = G->getTargetTriple();
240*bdd1243dSDimitry Andric   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
241*bdd1243dSDimitry Andric     if (auto MarkLive = Ctx->getMarkLivePass(TT))
242*bdd1243dSDimitry Andric       Config.PrePrunePasses.push_back(std::move(MarkLive));
243*bdd1243dSDimitry Andric     else
244*bdd1243dSDimitry Andric       Config.PrePrunePasses.push_back(markAllSymbolsLive);
245*bdd1243dSDimitry Andric 
246*bdd1243dSDimitry Andric     // Add an in-place GOT build pass.
247*bdd1243dSDimitry Andric     Config.PostPrunePasses.push_back(buildTables_ELF_i386);
248*bdd1243dSDimitry Andric   }
249*bdd1243dSDimitry Andric   if (auto Err = Ctx->modifyPassConfig(*G, Config))
250*bdd1243dSDimitry Andric     return Ctx->notifyFailed(std::move(Err));
251*bdd1243dSDimitry Andric 
252*bdd1243dSDimitry Andric   ELFJITLinker_i386::link(std::move(Ctx), std::move(G), std::move(Config));
253*bdd1243dSDimitry Andric }
254*bdd1243dSDimitry Andric 
255*bdd1243dSDimitry Andric } // namespace llvm::jitlink
256