1*06c3fb27SDimitry Andric //===----- ELF_aarch32.cpp - JIT linker implementation for arm/thumb ------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric // 9*06c3fb27SDimitry Andric // ELF/aarch32 jit-link implementation. 10*06c3fb27SDimitry Andric // 11*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 12*06c3fb27SDimitry Andric 13*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h" 14*06c3fb27SDimitry Andric 15*06c3fb27SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 16*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 17*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch32.h" 18*06c3fb27SDimitry Andric #include "llvm/Object/ELF.h" 19*06c3fb27SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 20*06c3fb27SDimitry Andric #include "llvm/Support/Endian.h" 21*06c3fb27SDimitry Andric #include "llvm/Support/ErrorHandling.h" 22*06c3fb27SDimitry Andric #include "llvm/TargetParser/ARMTargetParser.h" 23*06c3fb27SDimitry Andric 24*06c3fb27SDimitry Andric #include "ELFLinkGraphBuilder.h" 25*06c3fb27SDimitry Andric #include "JITLinkGeneric.h" 26*06c3fb27SDimitry Andric 27*06c3fb27SDimitry Andric #define DEBUG_TYPE "jitlink" 28*06c3fb27SDimitry Andric 29*06c3fb27SDimitry Andric using namespace llvm::object; 30*06c3fb27SDimitry Andric 31*06c3fb27SDimitry Andric namespace llvm { 32*06c3fb27SDimitry Andric namespace jitlink { 33*06c3fb27SDimitry Andric 34*06c3fb27SDimitry Andric /// Translate from ELF relocation type to JITLink-internal edge kind. 35*06c3fb27SDimitry Andric Expected<aarch32::EdgeKind_aarch32> getJITLinkEdgeKind(uint32_t ELFType) { 36*06c3fb27SDimitry Andric switch (ELFType) { 37*06c3fb27SDimitry Andric case ELF::R_ARM_ABS32: 38*06c3fb27SDimitry Andric return aarch32::Data_Pointer32; 39*06c3fb27SDimitry Andric case ELF::R_ARM_REL32: 40*06c3fb27SDimitry Andric return aarch32::Data_Delta32; 41*06c3fb27SDimitry Andric case ELF::R_ARM_CALL: 42*06c3fb27SDimitry Andric return aarch32::Arm_Call; 43*06c3fb27SDimitry Andric case ELF::R_ARM_THM_CALL: 44*06c3fb27SDimitry Andric return aarch32::Thumb_Call; 45*06c3fb27SDimitry Andric case ELF::R_ARM_THM_JUMP24: 46*06c3fb27SDimitry Andric return aarch32::Thumb_Jump24; 47*06c3fb27SDimitry Andric case ELF::R_ARM_THM_MOVW_ABS_NC: 48*06c3fb27SDimitry Andric return aarch32::Thumb_MovwAbsNC; 49*06c3fb27SDimitry Andric case ELF::R_ARM_THM_MOVT_ABS: 50*06c3fb27SDimitry Andric return aarch32::Thumb_MovtAbs; 51*06c3fb27SDimitry Andric } 52*06c3fb27SDimitry Andric 53*06c3fb27SDimitry Andric return make_error<JITLinkError>( 54*06c3fb27SDimitry Andric "Unsupported aarch32 relocation " + formatv("{0:d}: ", ELFType) + 55*06c3fb27SDimitry Andric object::getELFRelocationTypeName(ELF::EM_ARM, ELFType)); 56*06c3fb27SDimitry Andric } 57*06c3fb27SDimitry Andric 58*06c3fb27SDimitry Andric /// Translate from JITLink-internal edge kind back to ELF relocation type. 59*06c3fb27SDimitry Andric Expected<uint32_t> getELFRelocationType(Edge::Kind Kind) { 60*06c3fb27SDimitry Andric switch (static_cast<aarch32::EdgeKind_aarch32>(Kind)) { 61*06c3fb27SDimitry Andric case aarch32::Data_Delta32: 62*06c3fb27SDimitry Andric return ELF::R_ARM_REL32; 63*06c3fb27SDimitry Andric case aarch32::Data_Pointer32: 64*06c3fb27SDimitry Andric return ELF::R_ARM_ABS32; 65*06c3fb27SDimitry Andric case aarch32::Arm_Call: 66*06c3fb27SDimitry Andric return ELF::R_ARM_CALL; 67*06c3fb27SDimitry Andric case aarch32::Thumb_Call: 68*06c3fb27SDimitry Andric return ELF::R_ARM_THM_CALL; 69*06c3fb27SDimitry Andric case aarch32::Thumb_Jump24: 70*06c3fb27SDimitry Andric return ELF::R_ARM_THM_JUMP24; 71*06c3fb27SDimitry Andric case aarch32::Thumb_MovwAbsNC: 72*06c3fb27SDimitry Andric return ELF::R_ARM_THM_MOVW_ABS_NC; 73*06c3fb27SDimitry Andric case aarch32::Thumb_MovtAbs: 74*06c3fb27SDimitry Andric return ELF::R_ARM_THM_MOVT_ABS; 75*06c3fb27SDimitry Andric } 76*06c3fb27SDimitry Andric 77*06c3fb27SDimitry Andric return make_error<JITLinkError>(formatv("Invalid aarch32 edge {0:d}: ", 78*06c3fb27SDimitry Andric Kind)); 79*06c3fb27SDimitry Andric } 80*06c3fb27SDimitry Andric 81*06c3fb27SDimitry Andric /// Get a human-readable name for the given ELF AArch32 edge kind. 82*06c3fb27SDimitry Andric const char *getELFAArch32EdgeKindName(Edge::Kind R) { 83*06c3fb27SDimitry Andric // No ELF-specific edge kinds yet 84*06c3fb27SDimitry Andric return aarch32::getEdgeKindName(R); 85*06c3fb27SDimitry Andric } 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric class ELFJITLinker_aarch32 : public JITLinker<ELFJITLinker_aarch32> { 88*06c3fb27SDimitry Andric friend class JITLinker<ELFJITLinker_aarch32>; 89*06c3fb27SDimitry Andric 90*06c3fb27SDimitry Andric public: 91*06c3fb27SDimitry Andric ELFJITLinker_aarch32(std::unique_ptr<JITLinkContext> Ctx, 92*06c3fb27SDimitry Andric std::unique_ptr<LinkGraph> G, PassConfiguration PassCfg, 93*06c3fb27SDimitry Andric aarch32::ArmConfig ArmCfg) 94*06c3fb27SDimitry Andric : JITLinker(std::move(Ctx), std::move(G), std::move(PassCfg)), 95*06c3fb27SDimitry Andric ArmCfg(std::move(ArmCfg)) {} 96*06c3fb27SDimitry Andric 97*06c3fb27SDimitry Andric private: 98*06c3fb27SDimitry Andric aarch32::ArmConfig ArmCfg; 99*06c3fb27SDimitry Andric 100*06c3fb27SDimitry Andric Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 101*06c3fb27SDimitry Andric return aarch32::applyFixup(G, B, E, ArmCfg); 102*06c3fb27SDimitry Andric } 103*06c3fb27SDimitry Andric }; 104*06c3fb27SDimitry Andric 105*06c3fb27SDimitry Andric template <support::endianness DataEndianness> 106*06c3fb27SDimitry Andric class ELFLinkGraphBuilder_aarch32 107*06c3fb27SDimitry Andric : public ELFLinkGraphBuilder<ELFType<DataEndianness, false>> { 108*06c3fb27SDimitry Andric private: 109*06c3fb27SDimitry Andric using ELFT = ELFType<DataEndianness, false>; 110*06c3fb27SDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 111*06c3fb27SDimitry Andric 112*06c3fb27SDimitry Andric bool excludeSection(const typename ELFT::Shdr &Sect) const override { 113*06c3fb27SDimitry Andric // TODO: An .ARM.exidx (Exception Index table) entry is 8-bytes in size and 114*06c3fb27SDimitry Andric // consists of 2 words. It might be sufficient to process only relocations 115*06c3fb27SDimitry Andric // in the the second word (offset 4). Please find more details in: Exception 116*06c3fb27SDimitry Andric // Handling ABI for the Arm® Architecture -> Index table entries 117*06c3fb27SDimitry Andric if (Sect.sh_type == ELF::SHT_ARM_EXIDX) 118*06c3fb27SDimitry Andric return true; 119*06c3fb27SDimitry Andric return false; 120*06c3fb27SDimitry Andric } 121*06c3fb27SDimitry Andric 122*06c3fb27SDimitry Andric Error addRelocations() override { 123*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 124*06c3fb27SDimitry Andric using Self = ELFLinkGraphBuilder_aarch32<DataEndianness>; 125*06c3fb27SDimitry Andric for (const auto &RelSect : Base::Sections) { 126*06c3fb27SDimitry Andric if (Error Err = Base::forEachRelRelocation(RelSect, this, 127*06c3fb27SDimitry Andric &Self::addSingleRelRelocation)) 128*06c3fb27SDimitry Andric return Err; 129*06c3fb27SDimitry Andric } 130*06c3fb27SDimitry Andric return Error::success(); 131*06c3fb27SDimitry Andric } 132*06c3fb27SDimitry Andric 133*06c3fb27SDimitry Andric Error addSingleRelRelocation(const typename ELFT::Rel &Rel, 134*06c3fb27SDimitry Andric const typename ELFT::Shdr &FixupSect, 135*06c3fb27SDimitry Andric Block &BlockToFix) { 136*06c3fb27SDimitry Andric uint32_t SymbolIndex = Rel.getSymbol(false); 137*06c3fb27SDimitry Andric auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 138*06c3fb27SDimitry Andric if (!ObjSymbol) 139*06c3fb27SDimitry Andric return ObjSymbol.takeError(); 140*06c3fb27SDimitry Andric 141*06c3fb27SDimitry Andric Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 142*06c3fb27SDimitry Andric if (!GraphSymbol) 143*06c3fb27SDimitry Andric return make_error<StringError>( 144*06c3fb27SDimitry Andric formatv("Could not find symbol at given index, did you add it to " 145*06c3fb27SDimitry Andric "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 146*06c3fb27SDimitry Andric SymbolIndex, (*ObjSymbol)->st_shndx, 147*06c3fb27SDimitry Andric Base::GraphSymbols.size()), 148*06c3fb27SDimitry Andric inconvertibleErrorCode()); 149*06c3fb27SDimitry Andric 150*06c3fb27SDimitry Andric uint32_t Type = Rel.getType(false); 151*06c3fb27SDimitry Andric Expected<aarch32::EdgeKind_aarch32> Kind = getJITLinkEdgeKind(Type); 152*06c3fb27SDimitry Andric if (!Kind) 153*06c3fb27SDimitry Andric return Kind.takeError(); 154*06c3fb27SDimitry Andric 155*06c3fb27SDimitry Andric auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset; 156*06c3fb27SDimitry Andric Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 157*06c3fb27SDimitry Andric Edge E(*Kind, Offset, *GraphSymbol, 0); 158*06c3fb27SDimitry Andric 159*06c3fb27SDimitry Andric Expected<int64_t> Addend = 160*06c3fb27SDimitry Andric aarch32::readAddend(*Base::G, BlockToFix, E, ArmCfg); 161*06c3fb27SDimitry Andric if (!Addend) 162*06c3fb27SDimitry Andric return Addend.takeError(); 163*06c3fb27SDimitry Andric 164*06c3fb27SDimitry Andric E.setAddend(*Addend); 165*06c3fb27SDimitry Andric LLVM_DEBUG({ 166*06c3fb27SDimitry Andric dbgs() << " "; 167*06c3fb27SDimitry Andric printEdge(dbgs(), BlockToFix, E, getELFAArch32EdgeKindName(*Kind)); 168*06c3fb27SDimitry Andric dbgs() << "\n"; 169*06c3fb27SDimitry Andric }); 170*06c3fb27SDimitry Andric 171*06c3fb27SDimitry Andric BlockToFix.addEdge(std::move(E)); 172*06c3fb27SDimitry Andric return Error::success(); 173*06c3fb27SDimitry Andric } 174*06c3fb27SDimitry Andric 175*06c3fb27SDimitry Andric aarch32::ArmConfig ArmCfg; 176*06c3fb27SDimitry Andric 177*06c3fb27SDimitry Andric protected: 178*06c3fb27SDimitry Andric TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) override { 179*06c3fb27SDimitry Andric if (Sym.getValue() & 0x01) 180*06c3fb27SDimitry Andric return aarch32::ThumbSymbol; 181*06c3fb27SDimitry Andric return TargetFlagsType{}; 182*06c3fb27SDimitry Andric } 183*06c3fb27SDimitry Andric 184*06c3fb27SDimitry Andric orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym, 185*06c3fb27SDimitry Andric TargetFlagsType Flags) override { 186*06c3fb27SDimitry Andric assert((makeTargetFlags(Sym) & Flags) == Flags); 187*06c3fb27SDimitry Andric static constexpr uint64_t ThumbBit = 0x01; 188*06c3fb27SDimitry Andric return Sym.getValue() & ~ThumbBit; 189*06c3fb27SDimitry Andric } 190*06c3fb27SDimitry Andric 191*06c3fb27SDimitry Andric public: 192*06c3fb27SDimitry Andric ELFLinkGraphBuilder_aarch32(StringRef FileName, 193*06c3fb27SDimitry Andric const llvm::object::ELFFile<ELFT> &Obj, Triple TT, 194*06c3fb27SDimitry Andric SubtargetFeatures Features, 195*06c3fb27SDimitry Andric aarch32::ArmConfig ArmCfg) 196*06c3fb27SDimitry Andric : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features), 197*06c3fb27SDimitry Andric FileName, getELFAArch32EdgeKindName), 198*06c3fb27SDimitry Andric ArmCfg(std::move(ArmCfg)) {} 199*06c3fb27SDimitry Andric }; 200*06c3fb27SDimitry Andric 201*06c3fb27SDimitry Andric template <aarch32::StubsFlavor Flavor> 202*06c3fb27SDimitry Andric Error buildTables_ELF_aarch32(LinkGraph &G) { 203*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 204*06c3fb27SDimitry Andric 205*06c3fb27SDimitry Andric aarch32::StubsManager<Flavor> PLT; 206*06c3fb27SDimitry Andric visitExistingEdges(G, PLT); 207*06c3fb27SDimitry Andric return Error::success(); 208*06c3fb27SDimitry Andric } 209*06c3fb27SDimitry Andric 210*06c3fb27SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 211*06c3fb27SDimitry Andric createLinkGraphFromELFObject_aarch32(MemoryBufferRef ObjectBuffer) { 212*06c3fb27SDimitry Andric LLVM_DEBUG({ 213*06c3fb27SDimitry Andric dbgs() << "Building jitlink graph for new input " 214*06c3fb27SDimitry Andric << ObjectBuffer.getBufferIdentifier() << "...\n"; 215*06c3fb27SDimitry Andric }); 216*06c3fb27SDimitry Andric 217*06c3fb27SDimitry Andric auto ELFObj = ObjectFile::createELFObjectFile(ObjectBuffer); 218*06c3fb27SDimitry Andric if (!ELFObj) 219*06c3fb27SDimitry Andric return ELFObj.takeError(); 220*06c3fb27SDimitry Andric 221*06c3fb27SDimitry Andric auto Features = (*ELFObj)->getFeatures(); 222*06c3fb27SDimitry Andric if (!Features) 223*06c3fb27SDimitry Andric return Features.takeError(); 224*06c3fb27SDimitry Andric 225*06c3fb27SDimitry Andric // Find out what exact AArch32 instruction set and features we target. 226*06c3fb27SDimitry Andric auto TT = (*ELFObj)->makeTriple(); 227*06c3fb27SDimitry Andric ARM::ArchKind AK = ARM::parseArch(TT.getArchName()); 228*06c3fb27SDimitry Andric if (AK == ARM::ArchKind::INVALID) 229*06c3fb27SDimitry Andric return make_error<JITLinkError>( 230*06c3fb27SDimitry Andric "Failed to build ELF link graph: Invalid ARM ArchKind"); 231*06c3fb27SDimitry Andric 232*06c3fb27SDimitry Andric // Resolve our internal configuration for the target. If at some point the 233*06c3fb27SDimitry Andric // CPUArch alone becomes too unprecise, we can find more details in the 234*06c3fb27SDimitry Andric // Tag_CPU_arch_profile. 235*06c3fb27SDimitry Andric aarch32::ArmConfig ArmCfg; 236*06c3fb27SDimitry Andric using namespace ARMBuildAttrs; 237*06c3fb27SDimitry Andric auto Arch = static_cast<CPUArch>(ARM::getArchAttr(AK)); 238*06c3fb27SDimitry Andric switch (Arch) { 239*06c3fb27SDimitry Andric case v7: 240*06c3fb27SDimitry Andric case v8_A: 241*06c3fb27SDimitry Andric ArmCfg = aarch32::getArmConfigForCPUArch(Arch); 242*06c3fb27SDimitry Andric assert(ArmCfg.Stubs != aarch32::Unsupported && 243*06c3fb27SDimitry Andric "Provide a config for each supported CPU"); 244*06c3fb27SDimitry Andric break; 245*06c3fb27SDimitry Andric default: 246*06c3fb27SDimitry Andric return make_error<JITLinkError>( 247*06c3fb27SDimitry Andric "Failed to build ELF link graph: Unsupported CPU arch " + 248*06c3fb27SDimitry Andric StringRef(aarch32::getCPUArchName(Arch))); 249*06c3fb27SDimitry Andric } 250*06c3fb27SDimitry Andric 251*06c3fb27SDimitry Andric // Populate the link-graph. 252*06c3fb27SDimitry Andric switch (TT.getArch()) { 253*06c3fb27SDimitry Andric case Triple::arm: 254*06c3fb27SDimitry Andric case Triple::thumb: { 255*06c3fb27SDimitry Andric auto &ELFFile = cast<ELFObjectFile<ELF32LE>>(**ELFObj).getELFFile(); 256*06c3fb27SDimitry Andric return ELFLinkGraphBuilder_aarch32<support::little>( 257*06c3fb27SDimitry Andric (*ELFObj)->getFileName(), ELFFile, TT, std::move(*Features), 258*06c3fb27SDimitry Andric ArmCfg) 259*06c3fb27SDimitry Andric .buildGraph(); 260*06c3fb27SDimitry Andric } 261*06c3fb27SDimitry Andric case Triple::armeb: 262*06c3fb27SDimitry Andric case Triple::thumbeb: { 263*06c3fb27SDimitry Andric auto &ELFFile = cast<ELFObjectFile<ELF32BE>>(**ELFObj).getELFFile(); 264*06c3fb27SDimitry Andric return ELFLinkGraphBuilder_aarch32<support::big>( 265*06c3fb27SDimitry Andric (*ELFObj)->getFileName(), ELFFile, TT, std::move(*Features), 266*06c3fb27SDimitry Andric ArmCfg) 267*06c3fb27SDimitry Andric .buildGraph(); 268*06c3fb27SDimitry Andric } 269*06c3fb27SDimitry Andric default: 270*06c3fb27SDimitry Andric return make_error<JITLinkError>( 271*06c3fb27SDimitry Andric "Failed to build ELF/aarch32 link graph: Invalid target triple " + 272*06c3fb27SDimitry Andric TT.getTriple()); 273*06c3fb27SDimitry Andric } 274*06c3fb27SDimitry Andric } 275*06c3fb27SDimitry Andric 276*06c3fb27SDimitry Andric void link_ELF_aarch32(std::unique_ptr<LinkGraph> G, 277*06c3fb27SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 278*06c3fb27SDimitry Andric const Triple &TT = G->getTargetTriple(); 279*06c3fb27SDimitry Andric 280*06c3fb27SDimitry Andric using namespace ARMBuildAttrs; 281*06c3fb27SDimitry Andric ARM::ArchKind AK = ARM::parseArch(TT.getArchName()); 282*06c3fb27SDimitry Andric auto CPU = static_cast<CPUArch>(ARM::getArchAttr(AK)); 283*06c3fb27SDimitry Andric aarch32::ArmConfig ArmCfg = aarch32::getArmConfigForCPUArch(CPU); 284*06c3fb27SDimitry Andric 285*06c3fb27SDimitry Andric PassConfiguration PassCfg; 286*06c3fb27SDimitry Andric if (Ctx->shouldAddDefaultTargetPasses(TT)) { 287*06c3fb27SDimitry Andric // Add a mark-live pass. 288*06c3fb27SDimitry Andric if (auto MarkLive = Ctx->getMarkLivePass(TT)) 289*06c3fb27SDimitry Andric PassCfg.PrePrunePasses.push_back(std::move(MarkLive)); 290*06c3fb27SDimitry Andric else 291*06c3fb27SDimitry Andric PassCfg.PrePrunePasses.push_back(markAllSymbolsLive); 292*06c3fb27SDimitry Andric 293*06c3fb27SDimitry Andric switch (ArmCfg.Stubs) { 294*06c3fb27SDimitry Andric case aarch32::Thumbv7: 295*06c3fb27SDimitry Andric PassCfg.PostPrunePasses.push_back( 296*06c3fb27SDimitry Andric buildTables_ELF_aarch32<aarch32::Thumbv7>); 297*06c3fb27SDimitry Andric break; 298*06c3fb27SDimitry Andric case aarch32::Unsupported: 299*06c3fb27SDimitry Andric llvm_unreachable("Check before building graph"); 300*06c3fb27SDimitry Andric } 301*06c3fb27SDimitry Andric } 302*06c3fb27SDimitry Andric 303*06c3fb27SDimitry Andric if (auto Err = Ctx->modifyPassConfig(*G, PassCfg)) 304*06c3fb27SDimitry Andric return Ctx->notifyFailed(std::move(Err)); 305*06c3fb27SDimitry Andric 306*06c3fb27SDimitry Andric ELFJITLinker_aarch32::link(std::move(Ctx), std::move(G), std::move(PassCfg), 307*06c3fb27SDimitry Andric std::move(ArmCfg)); 308*06c3fb27SDimitry Andric } 309*06c3fb27SDimitry Andric 310*06c3fb27SDimitry Andric } // namespace jitlink 311*06c3fb27SDimitry Andric } // namespace llvm 312