1*bdd1243dSDimitry Andric //===--- ELF_loongarch.cpp - JIT linker implementation for ELF/loongarch --===// 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/loongarch jit-link implementation. 10*bdd1243dSDimitry Andric // 11*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12*bdd1243dSDimitry Andric 13*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h" 14*bdd1243dSDimitry Andric #include "llvm/BinaryFormat/ELF.h" 15*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 16*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 17*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/loongarch.h" 18*bdd1243dSDimitry Andric #include "llvm/Object/ELF.h" 19*bdd1243dSDimitry Andric #include "llvm/Object/ELFObjectFile.h" 20*bdd1243dSDimitry Andric 21*bdd1243dSDimitry Andric #include "EHFrameSupportImpl.h" 22*bdd1243dSDimitry Andric #include "ELFLinkGraphBuilder.h" 23*bdd1243dSDimitry Andric #include "JITLinkGeneric.h" 24*bdd1243dSDimitry Andric 25*bdd1243dSDimitry Andric #define DEBUG_TYPE "jitlink" 26*bdd1243dSDimitry Andric 27*bdd1243dSDimitry Andric using namespace llvm; 28*bdd1243dSDimitry Andric using namespace llvm::jitlink; 29*bdd1243dSDimitry Andric using namespace llvm::jitlink::loongarch; 30*bdd1243dSDimitry Andric 31*bdd1243dSDimitry Andric namespace { 32*bdd1243dSDimitry Andric 33*bdd1243dSDimitry Andric class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> { 34*bdd1243dSDimitry Andric friend class JITLinker<ELFJITLinker_loongarch>; 35*bdd1243dSDimitry Andric 36*bdd1243dSDimitry Andric public: 37*bdd1243dSDimitry Andric ELFJITLinker_loongarch(std::unique_ptr<JITLinkContext> Ctx, 38*bdd1243dSDimitry Andric std::unique_ptr<LinkGraph> G, 39*bdd1243dSDimitry Andric PassConfiguration PassConfig) 40*bdd1243dSDimitry Andric : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {} 41*bdd1243dSDimitry Andric 42*bdd1243dSDimitry Andric private: 43*bdd1243dSDimitry Andric Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 44*bdd1243dSDimitry Andric return loongarch::applyFixup(G, B, E); 45*bdd1243dSDimitry Andric } 46*bdd1243dSDimitry Andric }; 47*bdd1243dSDimitry Andric 48*bdd1243dSDimitry Andric template <typename ELFT> 49*bdd1243dSDimitry Andric class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> { 50*bdd1243dSDimitry Andric private: 51*bdd1243dSDimitry Andric static Expected<loongarch::EdgeKind_loongarch> 52*bdd1243dSDimitry Andric getRelocationKind(const uint32_t Type) { 53*bdd1243dSDimitry Andric using namespace loongarch; 54*bdd1243dSDimitry Andric switch (Type) { 55*bdd1243dSDimitry Andric case ELF::R_LARCH_64: 56*bdd1243dSDimitry Andric return Pointer64; 57*bdd1243dSDimitry Andric case ELF::R_LARCH_32: 58*bdd1243dSDimitry Andric return Pointer32; 59*bdd1243dSDimitry Andric case ELF::R_LARCH_32_PCREL: 60*bdd1243dSDimitry Andric return Delta32; 61*bdd1243dSDimitry Andric case ELF::R_LARCH_B26: 62*bdd1243dSDimitry Andric return Branch26PCRel; 63*bdd1243dSDimitry Andric case ELF::R_LARCH_PCALA_HI20: 64*bdd1243dSDimitry Andric return Page20; 65*bdd1243dSDimitry Andric case ELF::R_LARCH_PCALA_LO12: 66*bdd1243dSDimitry Andric return PageOffset12; 67*bdd1243dSDimitry Andric case ELF::R_LARCH_GOT_PC_HI20: 68*bdd1243dSDimitry Andric return RequestGOTAndTransformToPage20; 69*bdd1243dSDimitry Andric case ELF::R_LARCH_GOT_PC_LO12: 70*bdd1243dSDimitry Andric return RequestGOTAndTransformToPageOffset12; 71*bdd1243dSDimitry Andric } 72*bdd1243dSDimitry Andric 73*bdd1243dSDimitry Andric return make_error<JITLinkError>( 74*bdd1243dSDimitry Andric "Unsupported loongarch relocation:" + formatv("{0:d}: ", Type) + 75*bdd1243dSDimitry Andric object::getELFRelocationTypeName(ELF::EM_LOONGARCH, Type)); 76*bdd1243dSDimitry Andric } 77*bdd1243dSDimitry Andric 78*bdd1243dSDimitry Andric Error addRelocations() override { 79*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 80*bdd1243dSDimitry Andric 81*bdd1243dSDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 82*bdd1243dSDimitry Andric using Self = ELFLinkGraphBuilder_loongarch<ELFT>; 83*bdd1243dSDimitry Andric for (const auto &RelSect : Base::Sections) 84*bdd1243dSDimitry Andric if (Error Err = Base::forEachRelaRelocation(RelSect, this, 85*bdd1243dSDimitry Andric &Self::addSingleRelocation)) 86*bdd1243dSDimitry Andric return Err; 87*bdd1243dSDimitry Andric 88*bdd1243dSDimitry Andric return Error::success(); 89*bdd1243dSDimitry Andric } 90*bdd1243dSDimitry Andric 91*bdd1243dSDimitry Andric Error addSingleRelocation(const typename ELFT::Rela &Rel, 92*bdd1243dSDimitry Andric const typename ELFT::Shdr &FixupSect, 93*bdd1243dSDimitry Andric Block &BlockToFix) { 94*bdd1243dSDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 95*bdd1243dSDimitry Andric 96*bdd1243dSDimitry Andric uint32_t SymbolIndex = Rel.getSymbol(false); 97*bdd1243dSDimitry Andric auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 98*bdd1243dSDimitry Andric if (!ObjSymbol) 99*bdd1243dSDimitry Andric return ObjSymbol.takeError(); 100*bdd1243dSDimitry Andric 101*bdd1243dSDimitry Andric Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 102*bdd1243dSDimitry Andric if (!GraphSymbol) 103*bdd1243dSDimitry Andric return make_error<StringError>( 104*bdd1243dSDimitry Andric formatv("Could not find symbol at given index, did you add it to " 105*bdd1243dSDimitry Andric "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 106*bdd1243dSDimitry Andric SymbolIndex, (*ObjSymbol)->st_shndx, 107*bdd1243dSDimitry Andric Base::GraphSymbols.size()), 108*bdd1243dSDimitry Andric inconvertibleErrorCode()); 109*bdd1243dSDimitry Andric 110*bdd1243dSDimitry Andric uint32_t Type = Rel.getType(false); 111*bdd1243dSDimitry Andric Expected<loongarch::EdgeKind_loongarch> Kind = getRelocationKind(Type); 112*bdd1243dSDimitry Andric if (!Kind) 113*bdd1243dSDimitry Andric return Kind.takeError(); 114*bdd1243dSDimitry Andric 115*bdd1243dSDimitry Andric int64_t Addend = Rel.r_addend; 116*bdd1243dSDimitry Andric auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset; 117*bdd1243dSDimitry Andric Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 118*bdd1243dSDimitry Andric Edge GE(*Kind, Offset, *GraphSymbol, Addend); 119*bdd1243dSDimitry Andric LLVM_DEBUG({ 120*bdd1243dSDimitry Andric dbgs() << " "; 121*bdd1243dSDimitry Andric printEdge(dbgs(), BlockToFix, GE, loongarch::getEdgeKindName(*Kind)); 122*bdd1243dSDimitry Andric dbgs() << "\n"; 123*bdd1243dSDimitry Andric }); 124*bdd1243dSDimitry Andric 125*bdd1243dSDimitry Andric BlockToFix.addEdge(std::move(GE)); 126*bdd1243dSDimitry Andric 127*bdd1243dSDimitry Andric return Error::success(); 128*bdd1243dSDimitry Andric } 129*bdd1243dSDimitry Andric 130*bdd1243dSDimitry Andric public: 131*bdd1243dSDimitry Andric ELFLinkGraphBuilder_loongarch(StringRef FileName, 132*bdd1243dSDimitry Andric const object::ELFFile<ELFT> &Obj, 133*bdd1243dSDimitry Andric const Triple T) 134*bdd1243dSDimitry Andric : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName, 135*bdd1243dSDimitry Andric loongarch::getEdgeKindName) {} 136*bdd1243dSDimitry Andric }; 137*bdd1243dSDimitry Andric 138*bdd1243dSDimitry Andric Error buildTables_ELF_loongarch(LinkGraph &G) { 139*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 140*bdd1243dSDimitry Andric 141*bdd1243dSDimitry Andric GOTTableManager GOT; 142*bdd1243dSDimitry Andric PLTTableManager PLT(GOT); 143*bdd1243dSDimitry Andric visitExistingEdges(G, GOT, PLT); 144*bdd1243dSDimitry Andric return Error::success(); 145*bdd1243dSDimitry Andric } 146*bdd1243dSDimitry Andric 147*bdd1243dSDimitry Andric } // namespace 148*bdd1243dSDimitry Andric 149*bdd1243dSDimitry Andric namespace llvm { 150*bdd1243dSDimitry Andric namespace jitlink { 151*bdd1243dSDimitry Andric 152*bdd1243dSDimitry Andric Expected<std::unique_ptr<LinkGraph>> 153*bdd1243dSDimitry Andric createLinkGraphFromELFObject_loongarch(MemoryBufferRef ObjectBuffer) { 154*bdd1243dSDimitry Andric LLVM_DEBUG({ 155*bdd1243dSDimitry Andric dbgs() << "Building jitlink graph for new input " 156*bdd1243dSDimitry Andric << ObjectBuffer.getBufferIdentifier() << "...\n"; 157*bdd1243dSDimitry Andric }); 158*bdd1243dSDimitry Andric 159*bdd1243dSDimitry Andric auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 160*bdd1243dSDimitry Andric if (!ELFObj) 161*bdd1243dSDimitry Andric return ELFObj.takeError(); 162*bdd1243dSDimitry Andric 163*bdd1243dSDimitry Andric if ((*ELFObj)->getArch() == Triple::loongarch64) { 164*bdd1243dSDimitry Andric auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj); 165*bdd1243dSDimitry Andric return ELFLinkGraphBuilder_loongarch<object::ELF64LE>( 166*bdd1243dSDimitry Andric (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), 167*bdd1243dSDimitry Andric (*ELFObj)->makeTriple()) 168*bdd1243dSDimitry Andric .buildGraph(); 169*bdd1243dSDimitry Andric } 170*bdd1243dSDimitry Andric 171*bdd1243dSDimitry Andric assert((*ELFObj)->getArch() == Triple::loongarch32 && 172*bdd1243dSDimitry Andric "Invalid triple for LoongArch ELF object file"); 173*bdd1243dSDimitry Andric auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj); 174*bdd1243dSDimitry Andric return ELFLinkGraphBuilder_loongarch<object::ELF32LE>( 175*bdd1243dSDimitry Andric (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), 176*bdd1243dSDimitry Andric (*ELFObj)->makeTriple()) 177*bdd1243dSDimitry Andric .buildGraph(); 178*bdd1243dSDimitry Andric } 179*bdd1243dSDimitry Andric 180*bdd1243dSDimitry Andric void link_ELF_loongarch(std::unique_ptr<LinkGraph> G, 181*bdd1243dSDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 182*bdd1243dSDimitry Andric PassConfiguration Config; 183*bdd1243dSDimitry Andric const Triple &TT = G->getTargetTriple(); 184*bdd1243dSDimitry Andric if (Ctx->shouldAddDefaultTargetPasses(TT)) { 185*bdd1243dSDimitry Andric // Add eh-frame passses. 186*bdd1243dSDimitry Andric Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 187*bdd1243dSDimitry Andric Config.PrePrunePasses.push_back( 188*bdd1243dSDimitry Andric EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), Pointer32, Pointer64, 189*bdd1243dSDimitry Andric Delta32, Delta64, NegDelta32)); 190*bdd1243dSDimitry Andric Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 191*bdd1243dSDimitry Andric 192*bdd1243dSDimitry Andric // Add a mark-live pass. 193*bdd1243dSDimitry Andric if (auto MarkLive = Ctx->getMarkLivePass(TT)) 194*bdd1243dSDimitry Andric Config.PrePrunePasses.push_back(std::move(MarkLive)); 195*bdd1243dSDimitry Andric else 196*bdd1243dSDimitry Andric Config.PrePrunePasses.push_back(markAllSymbolsLive); 197*bdd1243dSDimitry Andric 198*bdd1243dSDimitry Andric // Add an in-place GOT/PLTStubs build pass. 199*bdd1243dSDimitry Andric Config.PostPrunePasses.push_back(buildTables_ELF_loongarch); 200*bdd1243dSDimitry Andric } 201*bdd1243dSDimitry Andric 202*bdd1243dSDimitry Andric if (auto Err = Ctx->modifyPassConfig(*G, Config)) 203*bdd1243dSDimitry Andric return Ctx->notifyFailed(std::move(Err)); 204*bdd1243dSDimitry Andric 205*bdd1243dSDimitry Andric ELFJITLinker_loongarch::link(std::move(Ctx), std::move(G), std::move(Config)); 206*bdd1243dSDimitry Andric } 207*bdd1243dSDimitry Andric 208*bdd1243dSDimitry Andric } // namespace jitlink 209*bdd1243dSDimitry Andric } // namespace llvm 210