1 //===-- RuntimeDyldMachOAArch64.h -- MachO/AArch64 specific code. -*- C++ -*-=//
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 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
10 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
12 #include "../RuntimeDyldMachO.h"
13 #include "llvm/Support/Endian.h"
15 #define DEBUG_TYPE "dyld"
19 class RuntimeDyldMachOAArch64
20 : public RuntimeDyldMachOCRTPBase
<RuntimeDyldMachOAArch64
> {
23 typedef uint64_t TargetPtrT
;
25 RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager
&MM
,
26 JITSymbolResolver
&Resolver
)
27 : RuntimeDyldMachOCRTPBase(MM
, Resolver
) {}
29 unsigned getMaxStubSize() const override
{ return 8; }
31 unsigned getStubAlignment() override
{ return 8; }
33 /// Extract the addend encoded in the instruction / memory location.
34 Expected
<int64_t> decodeAddend(const RelocationEntry
&RE
) const {
35 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
36 uint8_t *LocalAddress
= Section
.getAddressWithOffset(RE
.Offset
);
37 unsigned NumBytes
= 1 << RE
.Size
;
39 // Verify that the relocation has the correct size and alignment.
44 raw_string_ostream
ErrStream(ErrMsg
);
45 ErrStream
<< "Unsupported relocation type: "
46 << getRelocName(RE
.RelType
);
48 return make_error
<StringError
>(std::move(ErrMsg
),
49 inconvertibleErrorCode());
51 case MachO::ARM64_RELOC_POINTER_TO_GOT
:
52 case MachO::ARM64_RELOC_UNSIGNED
: {
53 if (NumBytes
!= 4 && NumBytes
!= 8) {
56 raw_string_ostream
ErrStream(ErrMsg
);
57 ErrStream
<< "Invalid relocation size for relocation "
58 << getRelocName(RE
.RelType
);
60 return make_error
<StringError
>(std::move(ErrMsg
),
61 inconvertibleErrorCode());
65 case MachO::ARM64_RELOC_BRANCH26
:
66 case MachO::ARM64_RELOC_PAGE21
:
67 case MachO::ARM64_RELOC_PAGEOFF12
:
68 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21
:
69 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12
:
70 assert(NumBytes
== 4 && "Invalid relocation size.");
71 assert((((uintptr_t)LocalAddress
& 0x3) == 0) &&
72 "Instruction address is not aligned to 4 bytes.");
78 llvm_unreachable("Unsupported relocation type!");
79 case MachO::ARM64_RELOC_POINTER_TO_GOT
:
80 case MachO::ARM64_RELOC_UNSIGNED
:
81 // This could be an unaligned memory location.
83 Addend
= *reinterpret_cast<support::ulittle32_t
*>(LocalAddress
);
85 Addend
= *reinterpret_cast<support::ulittle64_t
*>(LocalAddress
);
87 case MachO::ARM64_RELOC_BRANCH26
: {
88 // Verify that the relocation points to a B/BL instruction.
89 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
90 assert(((*p
& 0xFC000000) == 0x14000000 ||
91 (*p
& 0xFC000000) == 0x94000000) &&
92 "Expected branch instruction.");
94 // Get the 26 bit addend encoded in the branch instruction and sign-extend
95 // to 64 bit. The lower 2 bits are always zeros and are therefore implicit
97 Addend
= (*p
& 0x03FFFFFF) << 2;
98 Addend
= SignExtend64(Addend
, 28);
101 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21
:
102 case MachO::ARM64_RELOC_PAGE21
: {
103 // Verify that the relocation points to the expected adrp instruction.
104 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
105 assert((*p
& 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
107 // Get the 21 bit addend encoded in the adrp instruction and sign-extend
108 // to 64 bit. The lower 12 bits (4096 byte page) are always zeros and are
109 // therefore implicit (<< 12).
110 Addend
= ((*p
& 0x60000000) >> 29) | ((*p
& 0x01FFFFE0) >> 3) << 12;
111 Addend
= SignExtend64(Addend
, 33);
114 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12
: {
115 // Verify that the relocation points to one of the expected load / store
117 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
119 assert((*p
& 0x3B000000) == 0x39000000 &&
120 "Only expected load / store instructions.");
123 case MachO::ARM64_RELOC_PAGEOFF12
: {
124 // Verify that the relocation points to one of the expected load / store
125 // or add / sub instructions.
126 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
127 assert((((*p
& 0x3B000000) == 0x39000000) ||
128 ((*p
& 0x11C00000) == 0x11000000) ) &&
129 "Expected load / store or add/sub instruction.");
131 // Get the 12 bit addend encoded in the instruction.
132 Addend
= (*p
& 0x003FFC00) >> 10;
134 // Check which instruction we are decoding to obtain the implicit shift
135 // factor of the instruction.
136 int ImplicitShift
= 0;
137 if ((*p
& 0x3B000000) == 0x39000000) { // << load / store
138 // For load / store instructions the size is encoded in bits 31:30.
139 ImplicitShift
= ((*p
>> 30) & 0x3);
140 if (ImplicitShift
== 0) {
141 // Check if this a vector op to get the correct shift value.
142 if ((*p
& 0x04800000) == 0x04800000)
146 // Compensate for implicit shift.
147 Addend
<<= ImplicitShift
;
154 /// Extract the addend encoded in the instruction.
155 void encodeAddend(uint8_t *LocalAddress
, unsigned NumBytes
,
156 MachO::RelocationInfoType RelType
, int64_t Addend
) const {
157 // Verify that the relocation has the correct alignment.
160 llvm_unreachable("Unsupported relocation type!");
161 case MachO::ARM64_RELOC_POINTER_TO_GOT
:
162 case MachO::ARM64_RELOC_UNSIGNED
:
163 assert((NumBytes
== 4 || NumBytes
== 8) && "Invalid relocation size.");
165 case MachO::ARM64_RELOC_BRANCH26
:
166 case MachO::ARM64_RELOC_PAGE21
:
167 case MachO::ARM64_RELOC_PAGEOFF12
:
168 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21
:
169 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12
:
170 assert(NumBytes
== 4 && "Invalid relocation size.");
171 assert((((uintptr_t)LocalAddress
& 0x3) == 0) &&
172 "Instruction address is not aligned to 4 bytes.");
178 llvm_unreachable("Unsupported relocation type!");
179 case MachO::ARM64_RELOC_POINTER_TO_GOT
:
180 case MachO::ARM64_RELOC_UNSIGNED
:
181 // This could be an unaligned memory location.
183 *reinterpret_cast<support::ulittle32_t
*>(LocalAddress
) = Addend
;
185 *reinterpret_cast<support::ulittle64_t
*>(LocalAddress
) = Addend
;
187 case MachO::ARM64_RELOC_BRANCH26
: {
188 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
189 // Verify that the relocation points to the expected branch instruction.
190 assert(((*p
& 0xFC000000) == 0x14000000 ||
191 (*p
& 0xFC000000) == 0x94000000) &&
192 "Expected branch instruction.");
194 // Verify addend value.
195 assert((Addend
& 0x3) == 0 && "Branch target is not aligned");
196 assert(isInt
<28>(Addend
) && "Branch target is out of range.");
198 // Encode the addend as 26 bit immediate in the branch instruction.
199 *p
= (*p
& 0xFC000000) | ((uint32_t)(Addend
>> 2) & 0x03FFFFFF);
202 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21
:
203 case MachO::ARM64_RELOC_PAGE21
: {
204 // Verify that the relocation points to the expected adrp instruction.
205 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
206 assert((*p
& 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
208 // Check that the addend fits into 21 bits (+ 12 lower bits).
209 assert((Addend
& 0xFFF) == 0 && "ADRP target is not page aligned.");
210 assert(isInt
<33>(Addend
) && "Invalid page reloc value.");
212 // Encode the addend into the instruction.
213 uint32_t ImmLoValue
= ((uint64_t)Addend
<< 17) & 0x60000000;
214 uint32_t ImmHiValue
= ((uint64_t)Addend
>> 9) & 0x00FFFFE0;
215 *p
= (*p
& 0x9F00001F) | ImmHiValue
| ImmLoValue
;
218 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12
: {
219 // Verify that the relocation points to one of the expected load / store
221 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
222 assert((*p
& 0x3B000000) == 0x39000000 &&
223 "Only expected load / store instructions.");
227 case MachO::ARM64_RELOC_PAGEOFF12
: {
228 // Verify that the relocation points to one of the expected load / store
229 // or add / sub instructions.
230 auto *p
= reinterpret_cast<support::aligned_ulittle32_t
*>(LocalAddress
);
231 assert((((*p
& 0x3B000000) == 0x39000000) ||
232 ((*p
& 0x11C00000) == 0x11000000) ) &&
233 "Expected load / store or add/sub instruction.");
235 // Check which instruction we are decoding to obtain the implicit shift
236 // factor of the instruction and verify alignment.
237 int ImplicitShift
= 0;
238 if ((*p
& 0x3B000000) == 0x39000000) { // << load / store
239 // For load / store instructions the size is encoded in bits 31:30.
240 ImplicitShift
= ((*p
>> 30) & 0x3);
241 switch (ImplicitShift
) {
243 // Check if this a vector op to get the correct shift value.
244 if ((*p
& 0x04800000) == 0x04800000) {
246 assert(((Addend
& 0xF) == 0) &&
247 "128-bit LDR/STR not 16-byte aligned.");
251 assert(((Addend
& 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned.");
254 assert(((Addend
& 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned.");
257 assert(((Addend
& 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned.");
261 // Compensate for implicit shift.
262 Addend
>>= ImplicitShift
;
263 assert(isUInt
<12>(Addend
) && "Addend cannot be encoded.");
265 // Encode the addend into the instruction.
266 *p
= (*p
& 0xFFC003FF) | ((uint32_t)(Addend
<< 10) & 0x003FFC00);
272 Expected
<relocation_iterator
>
273 processRelocationRef(unsigned SectionID
, relocation_iterator RelI
,
274 const ObjectFile
&BaseObjT
,
275 ObjSectionToIDMap
&ObjSectionToID
,
276 StubMap
&Stubs
) override
{
277 const MachOObjectFile
&Obj
=
278 static_cast<const MachOObjectFile
&>(BaseObjT
);
279 MachO::any_relocation_info RelInfo
=
280 Obj
.getRelocation(RelI
->getRawDataRefImpl());
282 if (Obj
.isRelocationScattered(RelInfo
))
283 return make_error
<RuntimeDyldError
>("Scattered relocations not supported "
284 "for MachO AArch64");
286 // ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit
287 // addend for the following relocation. If found: (1) store the associated
288 // addend, (2) consume the next relocation, and (3) use the stored addend to
289 // override the addend.
290 int64_t ExplicitAddend
= 0;
291 if (Obj
.getAnyRelocationType(RelInfo
) == MachO::ARM64_RELOC_ADDEND
) {
292 assert(!Obj
.getPlainRelocationExternal(RelInfo
));
293 assert(!Obj
.getAnyRelocationPCRel(RelInfo
));
294 assert(Obj
.getAnyRelocationLength(RelInfo
) == 2);
295 int64_t RawAddend
= Obj
.getPlainRelocationSymbolNum(RelInfo
);
296 // Sign-extend the 24-bit to 64-bit.
297 ExplicitAddend
= SignExtend64(RawAddend
, 24);
299 RelInfo
= Obj
.getRelocation(RelI
->getRawDataRefImpl());
302 if (Obj
.getAnyRelocationType(RelInfo
) == MachO::ARM64_RELOC_SUBTRACTOR
)
303 return processSubtractRelocation(SectionID
, RelI
, Obj
, ObjSectionToID
);
305 RelocationEntry
RE(getRelocationEntry(SectionID
, Obj
, RelI
));
307 if (RE
.RelType
== MachO::ARM64_RELOC_POINTER_TO_GOT
) {
309 (RE
.Size
== 2 && RE
.IsPCRel
) || (RE
.Size
== 3 && !RE
.IsPCRel
);
311 return make_error
<StringError
>("ARM64_RELOC_POINTER_TO_GOT supports "
312 "32-bit pc-rel or 64-bit absolute only",
313 inconvertibleErrorCode());
316 if (auto Addend
= decodeAddend(RE
))
319 return Addend
.takeError();
321 assert((ExplicitAddend
== 0 || RE
.Addend
== 0) && "Relocation has "\
322 "ARM64_RELOC_ADDEND and embedded addend in the instruction.");
324 RE
.Addend
= ExplicitAddend
;
326 RelocationValueRef Value
;
327 if (auto ValueOrErr
= getRelocationValueRef(Obj
, RelI
, RE
, ObjSectionToID
))
330 return ValueOrErr
.takeError();
332 bool IsExtern
= Obj
.getPlainRelocationExternal(RelInfo
);
333 if (RE
.RelType
== MachO::ARM64_RELOC_POINTER_TO_GOT
) {
334 // We'll take care of the offset in processGOTRelocation.
336 } else if (!IsExtern
&& RE
.IsPCRel
)
337 makeValueAddendPCRel(Value
, RelI
, 1 << RE
.Size
);
339 RE
.Addend
= Value
.Offset
;
341 if (RE
.RelType
== MachO::ARM64_RELOC_GOT_LOAD_PAGE21
||
342 RE
.RelType
== MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12
||
343 RE
.RelType
== MachO::ARM64_RELOC_POINTER_TO_GOT
)
344 processGOTRelocation(RE
, Value
, Stubs
);
346 if (Value
.SymbolName
)
347 addRelocationForSymbol(RE
, Value
.SymbolName
);
349 addRelocationForSection(RE
, Value
.SectionID
);
355 void resolveRelocation(const RelocationEntry
&RE
, uint64_t Value
) override
{
356 LLVM_DEBUG(dumpRelocationToResolve(RE
, Value
));
358 const SectionEntry
&Section
= Sections
[RE
.SectionID
];
359 uint8_t *LocalAddress
= Section
.getAddressWithOffset(RE
.Offset
);
360 MachO::RelocationInfoType RelType
=
361 static_cast<MachO::RelocationInfoType
>(RE
.RelType
);
365 llvm_unreachable("Invalid relocation type!");
366 case MachO::ARM64_RELOC_UNSIGNED
: {
367 assert(!RE
.IsPCRel
&& "PCRel and ARM64_RELOC_UNSIGNED not supported");
368 // Mask in the target value a byte at a time (we don't have an alignment
369 // guarantee for the target address, so this is safest).
371 llvm_unreachable("Invalid size for ARM64_RELOC_UNSIGNED");
373 encodeAddend(LocalAddress
, 1 << RE
.Size
, RelType
, Value
+ RE
.Addend
);
377 case MachO::ARM64_RELOC_POINTER_TO_GOT
: {
378 assert(((RE
.Size
== 2 && RE
.IsPCRel
) || (RE
.Size
== 3 && !RE
.IsPCRel
)) &&
379 "ARM64_RELOC_POINTER_TO_GOT only supports 32-bit pc-rel or 64-bit "
381 // Addend is the GOT entry address and RE.Offset the target of the
384 RE
.IsPCRel
? (RE
.Addend
- RE
.Offset
) : (Value
+ RE
.Addend
);
385 encodeAddend(LocalAddress
, 1 << RE
.Size
, RelType
, Result
);
389 case MachO::ARM64_RELOC_BRANCH26
: {
390 assert(RE
.IsPCRel
&& "not PCRel and ARM64_RELOC_BRANCH26 not supported");
391 // Check if branch is in range.
392 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(RE
.Offset
);
393 int64_t PCRelVal
= Value
- FinalAddress
+ RE
.Addend
;
394 encodeAddend(LocalAddress
, /*Size=*/4, RelType
, PCRelVal
);
397 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21
:
398 case MachO::ARM64_RELOC_PAGE21
: {
399 assert(RE
.IsPCRel
&& "not PCRel and ARM64_RELOC_PAGE21 not supported");
400 // Adjust for PC-relative relocation and offset.
401 uint64_t FinalAddress
= Section
.getLoadAddressWithOffset(RE
.Offset
);
403 ((Value
+ RE
.Addend
) & (-4096)) - (FinalAddress
& (-4096));
404 encodeAddend(LocalAddress
, /*Size=*/4, RelType
, PCRelVal
);
407 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12
:
408 case MachO::ARM64_RELOC_PAGEOFF12
: {
409 assert(!RE
.IsPCRel
&& "PCRel and ARM64_RELOC_PAGEOFF21 not supported");
410 // Add the offset from the symbol.
412 // Mask out the page address and only use the lower 12 bits.
414 encodeAddend(LocalAddress
, /*Size=*/4, RelType
, Value
);
417 case MachO::ARM64_RELOC_SUBTRACTOR
: {
418 uint64_t SectionABase
= Sections
[RE
.Sections
.SectionA
].getLoadAddress();
419 uint64_t SectionBBase
= Sections
[RE
.Sections
.SectionB
].getLoadAddress();
420 assert((Value
== SectionABase
|| Value
== SectionBBase
) &&
421 "Unexpected SUBTRACTOR relocation value.");
422 Value
= SectionABase
- SectionBBase
+ RE
.Addend
;
423 writeBytesUnaligned(Value
, LocalAddress
, 1 << RE
.Size
);
427 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21
:
428 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12
:
429 llvm_unreachable("Relocation type not yet implemented!");
430 case MachO::ARM64_RELOC_ADDEND
:
431 llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by "
432 "processRelocationRef!");
436 Error
finalizeSection(const ObjectFile
&Obj
, unsigned SectionID
,
437 const SectionRef
&Section
) {
438 return Error::success();
442 void processGOTRelocation(const RelocationEntry
&RE
,
443 RelocationValueRef
&Value
, StubMap
&Stubs
) {
444 assert((RE
.RelType
== MachO::ARM64_RELOC_POINTER_TO_GOT
&&
445 (RE
.Size
== 2 || RE
.Size
== 3)) ||
447 SectionEntry
&Section
= Sections
[RE
.SectionID
];
448 StubMap::const_iterator i
= Stubs
.find(Value
);
450 if (i
!= Stubs
.end())
451 Offset
= static_cast<int64_t>(i
->second
);
453 // FIXME: There must be a better way to do this then to check and fix the
454 // alignment every time!!!
455 uintptr_t BaseAddress
= uintptr_t(Section
.getAddress());
456 uintptr_t StubAlignment
= getStubAlignment();
457 uintptr_t StubAddress
=
458 (BaseAddress
+ Section
.getStubOffset() + StubAlignment
- 1) &
460 unsigned StubOffset
= StubAddress
- BaseAddress
;
461 Stubs
[Value
] = StubOffset
;
462 assert(((StubAddress
% getStubAlignment()) == 0) &&
463 "GOT entry not aligned");
464 RelocationEntry
GOTRE(RE
.SectionID
, StubOffset
,
465 MachO::ARM64_RELOC_UNSIGNED
, Value
.Offset
,
466 /*IsPCRel=*/false, /*Size=*/3);
467 if (Value
.SymbolName
)
468 addRelocationForSymbol(GOTRE
, Value
.SymbolName
);
470 addRelocationForSection(GOTRE
, Value
.SectionID
);
471 Section
.advanceStubOffset(getMaxStubSize());
472 Offset
= static_cast<int64_t>(StubOffset
);
474 RelocationEntry
TargetRE(RE
.SectionID
, RE
.Offset
, RE
.RelType
, Offset
,
475 RE
.IsPCRel
, RE
.Size
);
476 addRelocationForSection(TargetRE
, RE
.SectionID
);
479 Expected
<relocation_iterator
>
480 processSubtractRelocation(unsigned SectionID
, relocation_iterator RelI
,
481 const ObjectFile
&BaseObjT
,
482 ObjSectionToIDMap
&ObjSectionToID
) {
483 const MachOObjectFile
&Obj
=
484 static_cast<const MachOObjectFile
&>(BaseObjT
);
485 MachO::any_relocation_info RE
=
486 Obj
.getRelocation(RelI
->getRawDataRefImpl());
488 unsigned Size
= Obj
.getAnyRelocationLength(RE
);
489 uint64_t Offset
= RelI
->getOffset();
490 uint8_t *LocalAddress
= Sections
[SectionID
].getAddressWithOffset(Offset
);
491 unsigned NumBytes
= 1 << Size
;
493 Expected
<StringRef
> SubtrahendNameOrErr
= RelI
->getSymbol()->getName();
494 if (!SubtrahendNameOrErr
)
495 return SubtrahendNameOrErr
.takeError();
496 auto SubtrahendI
= GlobalSymbolTable
.find(*SubtrahendNameOrErr
);
497 unsigned SectionBID
= SubtrahendI
->second
.getSectionID();
498 uint64_t SectionBOffset
= SubtrahendI
->second
.getOffset();
500 SignExtend64(readBytesUnaligned(LocalAddress
, NumBytes
), NumBytes
* 8);
503 Expected
<StringRef
> MinuendNameOrErr
= RelI
->getSymbol()->getName();
504 if (!MinuendNameOrErr
)
505 return MinuendNameOrErr
.takeError();
506 auto MinuendI
= GlobalSymbolTable
.find(*MinuendNameOrErr
);
507 unsigned SectionAID
= MinuendI
->second
.getSectionID();
508 uint64_t SectionAOffset
= MinuendI
->second
.getOffset();
510 RelocationEntry
R(SectionID
, Offset
, MachO::ARM64_RELOC_SUBTRACTOR
, (uint64_t)Addend
,
511 SectionAID
, SectionAOffset
, SectionBID
, SectionBOffset
,
514 addRelocationForSection(R
, SectionAID
);
519 static const char *getRelocName(uint32_t RelocType
) {
521 case MachO::ARM64_RELOC_UNSIGNED
: return "ARM64_RELOC_UNSIGNED";
522 case MachO::ARM64_RELOC_SUBTRACTOR
: return "ARM64_RELOC_SUBTRACTOR";
523 case MachO::ARM64_RELOC_BRANCH26
: return "ARM64_RELOC_BRANCH26";
524 case MachO::ARM64_RELOC_PAGE21
: return "ARM64_RELOC_PAGE21";
525 case MachO::ARM64_RELOC_PAGEOFF12
: return "ARM64_RELOC_PAGEOFF12";
526 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21
: return "ARM64_RELOC_GOT_LOAD_PAGE21";
527 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12
: return "ARM64_RELOC_GOT_LOAD_PAGEOFF12";
528 case MachO::ARM64_RELOC_POINTER_TO_GOT
: return "ARM64_RELOC_POINTER_TO_GOT";
529 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21
: return "ARM64_RELOC_TLVP_LOAD_PAGE21";
530 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12
: return "ARM64_RELOC_TLVP_LOAD_PAGEOFF12";
531 case MachO::ARM64_RELOC_ADDEND
: return "ARM64_RELOC_ADDEND";
533 return "Unrecognized arm64 addend";