1 //===----- ELF_aarch64.cpp - JIT linker implementation for ELF/aarch64 ----===// 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/aarch64 jit-link implementation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" 14 #include "ELFLinkGraphBuilder.h" 15 #include "JITLinkGeneric.h" 16 #include "llvm/BinaryFormat/ELF.h" 17 #include "llvm/ExecutionEngine/JITLink/aarch64.h" 18 #include "llvm/Object/ELFObjectFile.h" 19 #include "llvm/Support/MathExtras.h" 20 21 #define DEBUG_TYPE "jitlink" 22 23 using namespace llvm; 24 using namespace llvm::jitlink; 25 26 namespace llvm { 27 namespace jitlink { 28 29 class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> { 30 friend class JITLinker<ELFJITLinker_aarch64>; 31 32 public: 33 ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx, 34 std::unique_ptr<LinkGraph> G, 35 PassConfiguration PassConfig) 36 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {} 37 38 private: 39 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 40 using namespace aarch64; 41 using namespace llvm::support; 42 43 char *BlockWorkingMem = B.getAlreadyMutableContent().data(); 44 char *FixupPtr = BlockWorkingMem + E.getOffset(); 45 auto FixupAddress = B.getAddress() + E.getOffset(); 46 switch (E.getKind()) { 47 case aarch64::R_AARCH64_CALL26: { 48 assert((FixupAddress.getValue() & 0x3) == 0 && 49 "Call-inst is not 32-bit aligned"); 50 int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend(); 51 52 if (static_cast<uint64_t>(Value) & 0x3) 53 return make_error<JITLinkError>("Call target is not 32-bit aligned"); 54 55 if (!isInt<28>(Value)) 56 return makeTargetOutOfRangeError(G, B, E); 57 58 uint32_t RawInstr = *(little32_t *)FixupPtr; 59 assert((RawInstr & 0x7fffffff) == 0x14000000 && 60 "RawInstr isn't a B or BR immediate instruction"); 61 uint32_t Imm = (static_cast<uint32_t>(Value) & ((1 << 28) - 1)) >> 2; 62 uint32_t FixedInstr = RawInstr | Imm; 63 *(little32_t *)FixupPtr = FixedInstr; 64 break; 65 } 66 } 67 return Error::success(); 68 } 69 }; 70 71 template <typename ELFT> 72 class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> { 73 private: 74 static Expected<aarch64::EdgeKind_aarch64> 75 getRelocationKind(const uint32_t Type) { 76 using namespace aarch64; 77 switch (Type) { 78 case ELF::R_AARCH64_CALL26: 79 return EdgeKind_aarch64::R_AARCH64_CALL26; 80 } 81 82 return make_error<JITLinkError>("Unsupported aarch64 relocation:" + 83 formatv("{0:d}", Type)); 84 } 85 86 Error addRelocations() override { 87 LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 88 89 using Base = ELFLinkGraphBuilder<ELFT>; 90 using Self = ELFLinkGraphBuilder_aarch64<ELFT>; 91 for (const auto &RelSect : Base::Sections) 92 if (Error Err = Base::forEachRelocation(RelSect, this, 93 &Self::addSingleRelocation)) 94 return Err; 95 96 return Error::success(); 97 } 98 99 Error addSingleRelocation(const typename ELFT::Rela &Rel, 100 const typename ELFT::Shdr &FixupSect, 101 Block &BlockToFix) { 102 using Base = ELFLinkGraphBuilder<ELFT>; 103 104 uint32_t SymbolIndex = Rel.getSymbol(false); 105 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 106 if (!ObjSymbol) 107 return ObjSymbol.takeError(); 108 109 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 110 if (!GraphSymbol) 111 return make_error<StringError>( 112 formatv("Could not find symbol at given index, did you add it to " 113 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 114 SymbolIndex, (*ObjSymbol)->st_shndx, 115 Base::GraphSymbols.size()), 116 inconvertibleErrorCode()); 117 118 uint32_t Type = Rel.getType(false); 119 Expected<aarch64::EdgeKind_aarch64> Kind = getRelocationKind(Type); 120 if (!Kind) 121 return Kind.takeError(); 122 123 int64_t Addend = Rel.r_addend; 124 orc::ExecutorAddr FixupAddress = 125 orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset; 126 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 127 Edge GE(*Kind, Offset, *GraphSymbol, Addend); 128 LLVM_DEBUG({ 129 dbgs() << " "; 130 printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(*Kind)); 131 dbgs() << "\n"; 132 }); 133 134 BlockToFix.addEdge(std::move(GE)); 135 return Error::success(); 136 } 137 138 public: 139 ELFLinkGraphBuilder_aarch64(StringRef FileName, 140 const object::ELFFile<ELFT> &Obj, const Triple T) 141 : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName, 142 aarch64::getEdgeKindName) {} 143 }; 144 145 Expected<std::unique_ptr<LinkGraph>> 146 createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) { 147 LLVM_DEBUG({ 148 dbgs() << "Building jitlink graph for new input " 149 << ObjectBuffer.getBufferIdentifier() << "...\n"; 150 }); 151 152 auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 153 if (!ELFObj) 154 return ELFObj.takeError(); 155 156 assert((*ELFObj)->getArch() == Triple::aarch64 && 157 "Only AArch64 (little endian) is supported for now"); 158 159 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj); 160 return ELFLinkGraphBuilder_aarch64<object::ELF64LE>((*ELFObj)->getFileName(), 161 ELFObjFile.getELFFile(), 162 (*ELFObj)->makeTriple()) 163 .buildGraph(); 164 } 165 166 void link_ELF_aarch64(std::unique_ptr<LinkGraph> G, 167 std::unique_ptr<JITLinkContext> Ctx) { 168 PassConfiguration Config; 169 const Triple &TT = G->getTargetTriple(); 170 if (Ctx->shouldAddDefaultTargetPasses(TT)) { 171 if (auto MarkLive = Ctx->getMarkLivePass(TT)) 172 Config.PrePrunePasses.push_back(std::move(MarkLive)); 173 else 174 Config.PrePrunePasses.push_back(markAllSymbolsLive); 175 } 176 if (auto Err = Ctx->modifyPassConfig(*G, Config)) 177 return Ctx->notifyFailed(std::move(Err)); 178 179 ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config)); 180 } 181 182 } // namespace jitlink 183 } // namespace llvm 184