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