LLVM: lib/ExecutionEngine/JITLink/aarch64.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
14
16
17#define DEBUG_TYPE "jitlink"
18
19namespace llvm {
20namespace jitlink {
21namespace aarch64 {
22
24 0x00, 0x00, 0x00, 0x00};
25
27 0x10, 0x00, 0x00, (char)0x90u,
28 0x10, 0x02, 0x40, (char)0xf9u,
29 0x00, 0x02, 0x1f, (char)0xd6u
30};
31
33 (char)0xfd, 0x7b, (char)0xbf, (char)0xa9,
34 0x00, 0x00, 0x00, (char)0x94
35};
36
38 switch (R) {
40 return "Pointer64";
42 return "Pointer64Authenticated";
44 return "Pointer32";
46 return "Delta64";
48 return "Delta32";
50 return "NegDelta64";
52 return "NegDelta32";
54 return "Branch26PCRel";
56 return "MoveWide16";
58 return "LDRLiteral19";
60 return "TestAndBranch14PCRel";
62 return "CondBranch19PCRel";
64 return "ADRLiteral21";
66 return "Page21";
68 return "PageOffset12";
70 return "GotPageOffset15";
72 return "RequestGOTAndTransformToPage21";
74 return "RequestGOTAndTransformToPageOffset12";
76 return "RequestGOTAndTransformToPageOffset15";
78 return "RequestGOTAndTransformToDelta32";
80 return "RequestTLVPAndTransformToPage21";
82 return "RequestTLVPAndTransformToPageOffset12";
84 return "RequestTLSDescEntryAndTransformToPage21";
86 return "RequestTLSDescEntryAndTransformToPageOffset12";
87 default:
89 }
90}
91
92
93template
96 assert(DstReg < 32 && "Dst reg out of range");
97 assert(SrcReg < 32 && "Src reg out of range");
98
99 if (DstReg == SrcReg)
101
102 constexpr uint32_t MOVGPR64Template = 0xaa0003e0;
103 constexpr uint32_t DstRegIndex = 0;
104 constexpr uint32_t SrcRegIndex = 16;
105 uint32_t Instr = MOVGPR64Template;
106 Instr |= DstReg << DstRegIndex;
107 Instr |= SrcReg << SrcRegIndex;
108 return Append(Instr);
109}
110
111
112template
115 assert(Reg < 32 && "Invalid register number");
116
117 constexpr uint32_t MovRegImm64Template = 0xd2800000;
118 constexpr unsigned PreserveBitIndex = 29;
119 constexpr unsigned ShiftBitsIndex = 21;
120 constexpr unsigned ImmBitsIndex = 5;
121
122 bool PreserveRegValue = false;
123 for (unsigned I = 0; I != 4; ++I) {
124 uint32_t ImmBits = Imm & 0xffff;
125 Imm >>= 16;
126
127
128 if (PreserveRegValue && !ImmBits)
129 continue;
130
131 uint32_t Instr = MovRegImm64Template;
132 Instr |= PreserveRegValue << PreserveBitIndex;
133 Instr |= (I << ShiftBitsIndex);
134 Instr |= ImmBits << ImmBitsIndex;
135 Instr |= Reg;
136 if (auto Err = Append(Instr))
137 return Err;
138 PreserveRegValue = true;
139 }
140
142}
143
144template
147 unsigned RawAddrReg, unsigned DiscriminatorReg, unsigned Key,
148 uint64_t EncodedDiscriminator, bool AddressDiversify) {
149 assert(DstReg < 32 && "DstReg out of range");
150 assert(RawAddrReg < 32 && "AddrReg out of range");
151 assert(DiscriminatorReg < 32 && "DiscriminatorReg out of range");
152 assert(EncodedDiscriminator < 0x10000 && "EncodedDiscriminator out of range");
153
154 if (AddressDiversify) {
155
156 if (auto Err = writeMovRegRegSeq(Append, DiscriminatorReg, RawAddrReg))
157 return Err;
158
159 if (EncodedDiscriminator) {
160 constexpr uint32_t MOVKTemplate = 0xf2e00000;
161 constexpr unsigned ImmIndex = 5;
162 uint32_t BlendInstr = MOVKTemplate;
163 BlendInstr |= EncodedDiscriminator << ImmIndex;
164 BlendInstr |= DiscriminatorReg;
165 if (auto Err = Append(BlendInstr))
166 return Err;
167 }
168 } else if (EncodedDiscriminator) {
169
170 if (auto Err =
172 return Err;
173 } else
174 DiscriminatorReg = 31;
175
176 constexpr uint32_t PACTemplate = 0xdac10000;
177 constexpr unsigned ZBitIndex = 13;
178 constexpr unsigned KeyIndex = 10;
179 constexpr unsigned DiscriminatorRegIndex = 5;
180
181 uint32_t Instr = PACTemplate;
182 Instr |= (DiscriminatorReg == 31) << ZBitIndex;
183 Instr |= Key << KeyIndex;
184 Instr |= DiscriminatorReg << DiscriminatorRegIndex;
185 Instr |= DstReg;
186
187 return Append(Instr);
188}
189
190template
192 unsigned SrcReg) {
193 assert(DstLocReg < 32 && "DstLocReg out of range");
194 assert(SrcReg < 32 && "SrcReg out of range");
195
196 constexpr uint32_t STRTemplate = 0xf9000000;
197 constexpr unsigned DstLocRegIndex = 5;
198 constexpr unsigned SrcRegIndex = 0;
199
200 uint32_t Instr = STRTemplate;
201 Instr |= DstLocReg << DstLocRegIndex;
202 Instr |= SrcReg << SrcRegIndex;
203
204 return Append(Instr);
205}
206
207void GOTTableManager::registerExistingEntries() {
208 for (auto *EntrySym : GOTSection->symbols()) {
209 assert(EntrySym->getBlock().edges_size() == 1 &&
210 "GOT block edge count != 1");
212 *EntrySym);
213 }
214}
215
217 for (auto *EntrySym : StubsSection->symbols()) {
218 assert(EntrySym->getBlock().edges_size() == 2 &&
219 "PLT block edge count != 2");
220 auto &GOTSym = EntrySym->getBlock().edges().begin()->getTarget();
221 assert(GOTSym.getBlock().edges_size() == 1 && "GOT block edge count != 1");
223 *EntrySym);
224 }
225}
226
228
229
230
231
232
235 dbgs() << "Creating empty pointer signing function for " << G.getName()
236 << "\n";
237 });
238
239
240
241
242 size_t NumPtrAuthFixupLocations = 0;
243 for (auto &Sec : G.sections()) {
244
245
246
247
249 continue;
250
251 for (auto *B : Sec.blocks()) {
252 for (auto &E : B->edges())
253 NumPtrAuthFixupLocations +=
255 }
256 }
257
258 constexpr size_t MaxPtrSignSeqLength =
259 4 +
260 4 +
261 3 +
262 1;
263
264
265
266
267 size_t NumSigningInstrs = NumPtrAuthFixupLocations * MaxPtrSignSeqLength + 3;
268
269
270 auto &SigningSection =
274
275 size_t SigningFunctionSize = NumSigningInstrs * 4;
276 auto &SigningFunctionBlock = G.createMutableContentBlock(
277 SigningSection, G.allocateBuffer(SigningFunctionSize),
279 G.addAnonymousSymbol(SigningFunctionBlock, 0, SigningFunctionBlock.getSize(),
280 true, true);
281
283 dbgs() << " " << NumPtrAuthFixupLocations << " location(s) to sign, up to "
284 << NumSigningInstrs << " instructions required ("
285 << formatv("{0:x}", SigningFunctionBlock.getSize()) << " bytes)\n";
286 });
287
289}
290
291
292
293
294
295
296
299 dbgs() << "Writing pointer signing function for " << G.getName() << "\n";
300 });
301
302 constexpr unsigned Reg1 = 8;
303 constexpr unsigned Reg2 = 9;
304 constexpr unsigned Reg3 = 10;
305
306
307 auto *SigningSection =
309 assert(SigningSection && "Siging section missing");
310 assert(SigningSection->blocks_size() == 1 &&
311 "Unexpected number of blocks in signing section");
312 assert(SigningSection->symbols_size() == 1 &&
313 "Unexpected number of symbols in signing section");
314
315 auto &SigningFunctionSym = **SigningSection->symbols().begin();
316 auto &SigningFunctionBlock = SigningFunctionSym.getBlock();
317 auto SigningFunctionBuf = SigningFunctionBlock.getAlreadyMutableContent();
318
319
321 {reinterpret_cast<uint8_t *>(SigningFunctionBuf.data()),
322 SigningFunctionBuf.size()},
323 G.getEndianness());
324
325 auto AppendInstr = [&](uint32_t Instr) {
327 };
328
329 for (auto &Sec : G.sections()) {
330
332 continue;
333
334 for (auto *B : Sec.blocks()) {
335 for (auto &E : B->edges()) {
336
338 continue;
339
340 uint64_t EncodedInfo = E.getAddend();
341 int32_t RealAddend = (uint32_t)(EncodedInfo & 0xffffffff);
342 auto ValueToSign = E.getTarget().getAddress() + RealAddend;
343 if (!ValueToSign) {
344 LLVM_DEBUG(dbgs() << " " << B->getFixupAddress(E) << " <- null\n");
345 E.setAddend(RealAddend);
347 continue;
348 }
349
350 uint32_t InitialDiscriminator = (EncodedInfo >> 32) & 0xffff;
351 bool AddressDiversify = (EncodedInfo >> 48) & 0x1;
352 uint32_t Key = (EncodedInfo >> 49) & 0x3;
353 uint32_t HighBits = EncodedInfo >> 51;
354
355 if (HighBits != 0x1000)
357 "Pointer64Auth edge at " +
358 formatv("{0:x}", B->getFixupAddress(E).getValue()) +
359 " has invalid encoded addend " + formatv("{0:x}", EncodedInfo));
360
362 const char *const KeyNames[] = {"IA", "IB", "DA", "DB"};
363 dbgs() << " " << B->getFixupAddress(E) << " <- " << ValueToSign
364 << " : key = " << KeyNames[Key] << ", discriminator = "
365 << formatv("{0:x4}", InitialDiscriminator)
366 << ", address diversified = "
367 << (AddressDiversify ? "yes" : "no") << "\n";
368 });
369
370
373
374
376 B->getFixupAddress(E).getValue()));
377
378
380 Key, InitialDiscriminator, AddressDiversify));
381
382
384
385
386 E.setKind(Edge::KeepAlive);
387 }
388 }
389 }
390
391
392 constexpr uint32_t RETInstr = 0xd65f03c0;
395 cantFail(AppendInstr(RETInstr));
396
397
399 G.allocActions().push_back(
400 {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(
401 SigningFunctionSym.getAddress())),
402 {}});
403
405}
406
407}
408}
409}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Provides write only access to a subclass of WritableBinaryStream.
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
iterator_range< symbol_iterator > symbols()
Returns an iterator over the symbols defined in this section.
bool registerPreExistingEntry(Symbol &Target, Symbol &Entry)
LLVM_ABI void registerExistingEntries()
Definition aarch64.cpp:216
Represents an address in the executor process.
LLVM_ABI const char NullPointerContent[PointerSize]
AArch64 null pointer content.
Definition aarch64.cpp:23
static Error writeMovRegImm64Seq(AppendFtor &Append, uint64_t Reg, uint64_t Imm)
Definition aarch64.cpp:113
LLVM_ABI const char ReentryTrampolineContent[8]
AArch64 reentry trampoline.
Definition aarch64.cpp:32
static Error writeMovRegRegSeq(AppendFtor &Append, uint64_t DstReg, uint64_t SrcReg)
Definition aarch64.cpp:94
LLVM_ABI const char PointerJumpStubContent[12]
Definition aarch64.cpp:26
LLVM_ABI Error createEmptyPointerSigningFunction(LinkGraph &G)
Creates a pointer signing function section, block, and symbol to reserve space for a signing function...
Definition aarch64.cpp:233
LLVM_ABI Error lowerPointer64AuthEdgesToSigningFunction(LinkGraph &G)
Given a LinkGraph containing Pointer64Authenticated edges, transform those edges to Pointer64 and add...
Definition aarch64.cpp:297
LLVM_ABI const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
Definition aarch64.cpp:37
LLVM_ABI const char * getPointerSigningFunctionSectionName()
Returns the name of the pointer signing function section.
Definition aarch64.cpp:227
static Error writeStoreRegSeq(AppendFtor &Append, unsigned DstLocReg, unsigned SrcReg)
Definition aarch64.cpp:191
@ LDRLiteral19
The signed 21-bit delta from the fixup to the target.
@ Pointer64Authenticated
An arm64e authenticated pointer relocation.
@ RequestGOTAndTransformToPageOffset15
A GOT entry getter/constructor, transformed to Pageoffset15 pointing at the GOT entry for the origina...
@ CondBranch19PCRel
A 19-bit PC-relative conditional branch.
@ RequestTLVPAndTransformToPageOffset12
A TLVP entry getter/constructor, transformed to PageOffset12.
@ RequestTLSDescEntryAndTransformToPageOffset12
A TLSDesc entry getter/constructor, transformed to PageOffset12.
@ Page21
The signed 21-bit delta from the fixup page to the page containing the target.
@ Branch26PCRel
A 26-bit PC-relative branch.
@ Pointer64
A plain 64-bit pointer value relocation.
@ Pointer32
A plain 32-bit pointer value relocation.
@ RequestTLVPAndTransformToPage21
A TLVP entry getter/constructor, transformed to Page21.
@ GotPageOffset15
The 15-bit offset of the GOT entry from the GOT table.
@ MoveWide16
A 16-bit slice of the target address (which slice depends on the instruction at the fixup location).
@ TestAndBranch14PCRel
A 14-bit PC-relative test and branch.
@ RequestGOTAndTransformToPage21
A GOT entry getter/constructor, transformed to Page21 pointing at the GOT entry for the original targ...
@ ADRLiteral21
The signed 21-bit delta from the fixup to the target.
@ RequestGOTAndTransformToPageOffset12
A GOT entry getter/constructor, transformed to Pageoffset12 pointing at the GOT entry for the origina...
@ NegDelta32
A 32-bit negative delta.
@ NegDelta64
A 64-bit negative delta.
@ RequestGOTAndTransformToDelta32
A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT entry for the original tar...
@ PageOffset12
The 12-bit (potentially shifted) offset of the target within its page.
@ RequestTLSDescEntryAndTransformToPage21
A TLSDesc entry getter/constructor, transformed to Page21.
static Error writePACSignSeq(AppendFtor &Append, unsigned DstReg, orc::ExecutorAddr RawAddr, unsigned RawAddrReg, unsigned DiscriminatorReg, unsigned Key, uint64_t EncodedDiscriminator, bool AddressDiversify)
Definition aarch64.cpp:146
LLVM_ABI const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
@ NoAlloc
NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.
@ Finalize
Finalize memory should be allocated by the allocator, and then be overwritten and deallocated after a...
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.