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