1 //===----- ELF_aarch32.cpp - JIT linker implementation for arm/thumb ------===//
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
7 //===----------------------------------------------------------------------===//
9 // ELF/aarch32 jit-link implementation.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h"
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"
23 #include "ELFLinkGraphBuilder.h"
24 #include "JITLinkGeneric.h"
26 #define DEBUG_TYPE "jitlink"
28 using namespace llvm::object
;
33 /// Translate from ELF relocation type to JITLink-internal edge kind.
34 Expected
<aarch32::EdgeKind_aarch32
>
35 getJITLinkEdgeKind(uint32_t ELFType
, const aarch32::ArmConfig
&ArmCfg
) {
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
;
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
;
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
;
72 return make_error
<JITLinkError
>(
73 "Unsupported aarch32 relocation " + formatv("{0:d}: ", ELFType
) +
74 object::getELFRelocationTypeName(ELF::EM_ARM
, ELFType
));
77 /// Translate from JITLink-internal edge kind back to ELF relocation type.
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
;
109 return ELF::R_ARM_NONE
;
112 return make_error
<JITLinkError
>(formatv("Invalid aarch32 edge {0:d}: ",
116 /// Get a human-readable name for the given ELF AArch32 edge kind.
117 const char *getELFAArch32EdgeKindName(Edge::Kind R
) {
118 // No ELF-specific edge kinds yet
119 return aarch32::getEdgeKindName(R
);
122 class ELFJITLinker_aarch32
: public JITLinker
<ELFJITLinker_aarch32
> {
123 friend class JITLinker
<ELFJITLinker_aarch32
>;
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
)) {}
133 aarch32::ArmConfig ArmCfg
;
135 Error
applyFixup(LinkGraph
&G
, Block
&B
, const Edge
&E
) const {
136 return aarch32::applyFixup(G
, B
, E
, ArmCfg
);
140 template <llvm::endianness DataEndianness
>
141 class ELFLinkGraphBuilder_aarch32
142 : public ELFLinkGraphBuilder
<ELFType
<DataEndianness
, false>> {
144 using ELFT
= ELFType
<DataEndianness
, false>;
145 using Base
= ELFLinkGraphBuilder
<ELFT
>;
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
))
155 return Error::success();
158 Error
addSingleRelRelocation(const typename
ELFT::Rel
&Rel
,
159 const typename
ELFT::Shdr
&FixupSect
,
161 uint32_t SymbolIndex
= Rel
.getSymbol(false);
162 auto ObjSymbol
= Base::Obj
.getRelocationSymbol(Rel
, Base::SymTabSec
);
164 return ObjSymbol
.takeError();
166 Symbol
*GraphSymbol
= Base::getGraphSymbol(SymbolIndex
);
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());
175 uint32_t Type
= Rel
.getType(false);
176 Expected
<aarch32::EdgeKind_aarch32
> Kind
= getJITLinkEdgeKind(Type
, ArmCfg
);
178 return Kind
.takeError();
180 auto FixupAddress
= orc::ExecutorAddr(FixupSect
.sh_addr
) + Rel
.r_offset
;
181 Edge::OffsetT Offset
= FixupAddress
- BlockToFix
.getAddress();
183 Expected
<int64_t> Addend
=
184 aarch32::readAddend(*Base::G
, BlockToFix
, Offset
, *Kind
, ArmCfg
);
186 return Addend
.takeError();
188 Edge
E(*Kind
, Offset
, *GraphSymbol
, *Addend
);
191 printEdge(dbgs(), BlockToFix
, E
, getELFAArch32EdgeKindName(*Kind
));
195 BlockToFix
.addEdge(std::move(E
));
196 return Error::success();
199 aarch32::ArmConfig ArmCfg
;
202 TargetFlagsType
makeTargetFlags(const typename
ELFT::Sym
&Sym
) override
{
203 if (Sym
.getValue() & 0x01)
204 return aarch32::ThumbSymbol
;
205 return TargetFlagsType
{};
208 orc::ExecutorAddrDiff
getRawOffset(const typename
ELFT::Sym
&Sym
,
209 TargetFlagsType Flags
) override
{
210 assert((makeTargetFlags(Sym
) & Flags
) == Flags
);
211 static constexpr uint64_t ThumbBit
= 0x01;
212 return Sym
.getValue() & ~ThumbBit
;
216 ELFLinkGraphBuilder_aarch32(StringRef FileName
,
217 const llvm::object::ELFFile
<ELFT
> &Obj
, Triple TT
,
218 SubtargetFeatures Features
,
219 aarch32::ArmConfig ArmCfg
)
220 : ELFLinkGraphBuilder
<ELFT
>(Obj
, std::move(TT
), std::move(Features
),
221 FileName
, getELFAArch32EdgeKindName
),
222 ArmCfg(std::move(ArmCfg
)) {}
225 template <typename StubsManagerType
>
226 Error
buildTables_ELF_aarch32(LinkGraph
&G
) {
227 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
229 StubsManagerType StubsManager
;
230 visitExistingEdges(G
, StubsManager
);
231 aarch32::GOTBuilder GOT
;
232 visitExistingEdges(G
, GOT
);
234 return Error::success();
237 Expected
<std::unique_ptr
<LinkGraph
>>
238 createLinkGraphFromELFObject_aarch32(MemoryBufferRef ObjectBuffer
) {
240 dbgs() << "Building jitlink graph for new input "
241 << ObjectBuffer
.getBufferIdentifier() << "...\n";
244 auto ELFObj
= ObjectFile::createELFObjectFile(ObjectBuffer
);
246 return ELFObj
.takeError();
248 auto Features
= (*ELFObj
)->getFeatures();
250 return Features
.takeError();
252 // Find out what exact AArch32 instruction set and features we target.
253 auto TT
= (*ELFObj
)->makeTriple();
254 ARM::ArchKind AK
= ARM::parseArch(TT
.getArchName());
255 if (AK
== ARM::ArchKind::INVALID
)
256 return make_error
<JITLinkError
>(
257 "Failed to build ELF link graph: Invalid ARM ArchKind");
259 // Resolve our internal configuration for the target. If at some point the
260 // CPUArch alone becomes too unprecise, we can find more details in the
261 // Tag_CPU_arch_profile.
262 auto Arch
= static_cast<ARMBuildAttrs::CPUArch
>(ARM::getArchAttr(AK
));
263 aarch32::ArmConfig ArmCfg
= aarch32::getArmConfigForCPUArch(Arch
);
265 // Populate the link-graph.
266 switch (TT
.getArch()) {
268 case Triple::thumb
: {
269 auto &ELFFile
= cast
<ELFObjectFile
<ELF32LE
>>(**ELFObj
).getELFFile();
270 return ELFLinkGraphBuilder_aarch32
<llvm::endianness::little
>(
271 (*ELFObj
)->getFileName(), ELFFile
, TT
, std::move(*Features
),
276 case Triple::thumbeb
: {
277 auto &ELFFile
= cast
<ELFObjectFile
<ELF32BE
>>(**ELFObj
).getELFFile();
278 return ELFLinkGraphBuilder_aarch32
<llvm::endianness::big
>(
279 (*ELFObj
)->getFileName(), ELFFile
, TT
, std::move(*Features
),
284 return make_error
<JITLinkError
>(
285 "Failed to build ELF/aarch32 link graph: Invalid target triple " +
290 void link_ELF_aarch32(std::unique_ptr
<LinkGraph
> G
,
291 std::unique_ptr
<JITLinkContext
> Ctx
) {
292 const Triple
&TT
= G
->getTargetTriple();
294 using namespace ARMBuildAttrs
;
295 ARM::ArchKind AK
= ARM::parseArch(TT
.getArchName());
296 auto CPU
= static_cast<CPUArch
>(ARM::getArchAttr(AK
));
297 aarch32::ArmConfig ArmCfg
= aarch32::getArmConfigForCPUArch(CPU
);
299 PassConfiguration PassCfg
;
300 if (Ctx
->shouldAddDefaultTargetPasses(TT
)) {
301 // Add a mark-live pass.
302 if (auto MarkLive
= Ctx
->getMarkLivePass(TT
))
303 PassCfg
.PrePrunePasses
.push_back(std::move(MarkLive
));
305 PassCfg
.PrePrunePasses
.push_back(markAllSymbolsLive
);
307 switch (ArmCfg
.Stubs
) {
308 case aarch32::StubsFlavor::pre_v7
:
309 PassCfg
.PostPrunePasses
.push_back(
310 buildTables_ELF_aarch32
<aarch32::StubsManager_prev7
>);
312 case aarch32::StubsFlavor::v7
:
313 PassCfg
.PostPrunePasses
.push_back(
314 buildTables_ELF_aarch32
<aarch32::StubsManager_v7
>);
316 case aarch32::StubsFlavor::Undefined
:
317 llvm_unreachable("Check before building graph");
321 if (auto Err
= Ctx
->modifyPassConfig(*G
, PassCfg
))
322 return Ctx
->notifyFailed(std::move(Err
));
324 ELFJITLinker_aarch32::link(std::move(Ctx
), std::move(G
), std::move(PassCfg
),
328 } // namespace jitlink