542 lines · c
1//===-- RuntimeDyldMachOAArch64.h -- MachO/AArch64 specific code. -*- C++ -*-=//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H10#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H11 12#include "../RuntimeDyldMachO.h"13#include "llvm/Support/Endian.h"14 15#define DEBUG_TYPE "dyld"16 17namespace llvm {18 19class RuntimeDyldMachOAArch6420 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOAArch64> {21public:22 23 typedef uint64_t TargetPtrT;24 25 RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM,26 JITSymbolResolver &Resolver)27 : RuntimeDyldMachOCRTPBase(MM, Resolver) {}28 29 unsigned getMaxStubSize() const override { return 8; }30 31 Align getStubAlignment() override { return Align(8); }32 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;38 int64_t Addend = 0;39 // Verify that the relocation has the correct size and alignment.40 switch (RE.RelType) {41 default: {42 std::string ErrMsg;43 {44 raw_string_ostream ErrStream(ErrMsg);45 ErrStream << "Unsupported relocation type: "46 << getRelocName(RE.RelType);47 }48 return make_error<StringError>(std::move(ErrMsg),49 inconvertibleErrorCode());50 }51 case MachO::ARM64_RELOC_POINTER_TO_GOT:52 case MachO::ARM64_RELOC_UNSIGNED: {53 if (NumBytes != 4 && NumBytes != 8) {54 std::string ErrMsg;55 {56 raw_string_ostream ErrStream(ErrMsg);57 ErrStream << "Invalid relocation size for relocation "58 << getRelocName(RE.RelType);59 }60 return make_error<StringError>(std::move(ErrMsg),61 inconvertibleErrorCode());62 }63 break;64 }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.");73 break;74 }75 76 switch (RE.RelType) {77 default: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.82 if (NumBytes == 4)83 Addend = *reinterpret_cast<support::ulittle32_t *>(LocalAddress);84 else85 Addend = *reinterpret_cast<support::ulittle64_t *>(LocalAddress);86 break;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.");93 94 // Get the 26 bit addend encoded in the branch instruction and sign-extend95 // to 64 bit. The lower 2 bits are always zeros and are therefore implicit96 // (<< 2).97 Addend = (*p & 0x03FFFFFF) << 2;98 Addend = SignExtend64(Addend, 28);99 break;100 }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.");106 107 // Get the 21 bit addend encoded in the adrp instruction and sign-extend108 // to 64 bit. The lower 12 bits (4096 byte page) are always zeros and are109 // therefore implicit (<< 12).110 Addend = ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3) << 12;111 Addend = SignExtend64(Addend, 33);112 break;113 }114 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {115 // Verify that the relocation points to one of the expected load / store116 // instructions.117 auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);118 (void)p;119 assert((*p & 0x3B000000) == 0x39000000 &&120 "Only expected load / store instructions.");121 [[fallthrough]];122 }123 case MachO::ARM64_RELOC_PAGEOFF12: {124 // Verify that the relocation points to one of the expected load / store125 // 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.");130 131 // Get the 12 bit addend encoded in the instruction.132 Addend = (*p & 0x003FFC00) >> 10;133 134 // Check which instruction we are decoding to obtain the implicit shift135 // factor of the instruction.136 int ImplicitShift = 0;137 if ((*p & 0x3B000000) == 0x39000000) { // << load / store138 // 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)143 ImplicitShift = 4;144 }145 }146 // Compensate for implicit shift.147 Addend <<= ImplicitShift;148 break;149 }150 }151 return Addend;152 }153 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.158 switch (RelType) {159 default: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.");164 break;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.");173 break;174 }175 176 switch (RelType) {177 default: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.182 if (NumBytes == 4)183 *reinterpret_cast<support::ulittle32_t *>(LocalAddress) = Addend;184 else185 *reinterpret_cast<support::ulittle64_t *>(LocalAddress) = Addend;186 break;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.");193 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.");197 198 // Encode the addend as 26 bit immediate in the branch instruction.199 *p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF);200 break;201 }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.");207 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.");211 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;216 break;217 }218 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {219 // Verify that the relocation points to one of the expected load / store220 // instructions.221 auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);222 assert((*p & 0x3B000000) == 0x39000000 &&223 "Only expected load / store instructions.");224 (void)p;225 [[fallthrough]];226 }227 case MachO::ARM64_RELOC_PAGEOFF12: {228 // Verify that the relocation points to one of the expected load / store229 // 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.");234 235 // Check which instruction we are decoding to obtain the implicit shift236 // factor of the instruction and verify alignment.237 int ImplicitShift = 0;238 if ((*p & 0x3B000000) == 0x39000000) { // << load / store239 // For load / store instructions the size is encoded in bits 31:30.240 ImplicitShift = ((*p >> 30) & 0x3);241 switch (ImplicitShift) {242 case 0:243 // Check if this a vector op to get the correct shift value.244 if ((*p & 0x04800000) == 0x04800000) {245 ImplicitShift = 4;246 assert(((Addend & 0xF) == 0) &&247 "128-bit LDR/STR not 16-byte aligned.");248 }249 break;250 case 1:251 assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned.");252 break;253 case 2:254 assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned.");255 break;256 case 3:257 assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned.");258 break;259 }260 }261 // Compensate for implicit shift.262 Addend >>= ImplicitShift;263 assert(isUInt<12>(Addend) && "Addend cannot be encoded.");264 265 // Encode the addend into the instruction.266 *p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00);267 break;268 }269 }270 }271 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());281 282 if (Obj.isRelocationScattered(RelInfo))283 return make_error<RuntimeDyldError>("Scattered relocations not supported "284 "for MachO AArch64");285 286 // ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit287 // addend for the following relocation. If found: (1) store the associated288 // addend, (2) consume the next relocation, and (3) use the stored addend to289 // 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);298 ++RelI;299 RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());300 }301 302 if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_SUBTRACTOR)303 return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID);304 305 RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));306 307 if (RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT) {308 bool Valid =309 (RE.Size == 2 && RE.IsPCRel) || (RE.Size == 3 && !RE.IsPCRel);310 if (!Valid)311 return make_error<StringError>("ARM64_RELOC_POINTER_TO_GOT supports "312 "32-bit pc-rel or 64-bit absolute only",313 inconvertibleErrorCode());314 }315 316 if (auto Addend = decodeAddend(RE))317 RE.Addend = *Addend;318 else319 return Addend.takeError();320 321 assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\322 "ARM64_RELOC_ADDEND and embedded addend in the instruction.");323 if (ExplicitAddend)324 RE.Addend = ExplicitAddend;325 326 RelocationValueRef Value;327 if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))328 Value = *ValueOrErr;329 else330 return ValueOrErr.takeError();331 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.335 Value.Offset = 0;336 } else if (!IsExtern && RE.IsPCRel)337 makeValueAddendPCRel(Value, RelI, 1 << RE.Size);338 339 RE.Addend = Value.Offset;340 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);345 else {346 if (Value.SymbolName)347 addRelocationForSymbol(RE, Value.SymbolName);348 else349 addRelocationForSection(RE, Value.SectionID);350 }351 352 return ++RelI;353 }354 355 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {356 LLVM_DEBUG(dumpRelocationToResolve(RE, Value));357 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);362 363 switch (RelType) {364 default: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 alignment369 // guarantee for the target address, so this is safest).370 if (RE.Size < 2)371 llvm_unreachable("Invalid size for ARM64_RELOC_UNSIGNED");372 373 encodeAddend(LocalAddress, 1 << RE.Size, RelType, Value + RE.Addend);374 break;375 }376 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 "380 "absolute");381 // Addend is the GOT entry address and RE.Offset the target of the382 // relocation.383 uint64_t Result =384 RE.IsPCRel ? (RE.Addend - RE.Offset) : (Value + RE.Addend);385 encodeAddend(LocalAddress, 1 << RE.Size, RelType, Result);386 break;387 }388 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);395 break;396 }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);402 int64_t PCRelVal =403 ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));404 encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal);405 break;406 }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.411 Value += RE.Addend;412 // Mask out the page address and only use the lower 12 bits.413 Value &= 0xFFF;414 encodeAddend(LocalAddress, /*Size=*/4, RelType, Value);415 break;416 }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);424 break;425 }426 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!");433 }434 }435 436 Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,437 const SectionRef &Section) {438 return Error::success();439 }440 441private: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)) ||446 RE.Size == 2);447 SectionEntry &Section = Sections[RE.SectionID];448 auto [It, Inserted] = Stubs.try_emplace(Value);449 int64_t Offset;450 if (!Inserted)451 Offset = static_cast<int64_t>(It->second);452 else {453 // FIXME: There must be a better way to do this then to check and fix the454 // alignment every time!!!455 uintptr_t BaseAddress = uintptr_t(Section.getAddress());456 uintptr_t StubAlignment = getStubAlignment().value();457 uintptr_t StubAddress =458 (BaseAddress + Section.getStubOffset() + StubAlignment - 1) &459 -StubAlignment;460 unsigned StubOffset = StubAddress - BaseAddress;461 It->second = StubOffset;462 assert(isAligned(getStubAlignment(), StubAddress) &&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);469 else470 addRelocationForSection(GOTRE, Value.SectionID);471 Section.advanceStubOffset(getMaxStubSize());472 Offset = static_cast<int64_t>(StubOffset);473 }474 RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, Offset,475 RE.IsPCRel, RE.Size);476 addRelocationForSection(TargetRE, RE.SectionID);477 }478 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());487 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;492 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();499 int64_t Addend =500 SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8);501 502 ++RelI;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();509 510 RelocationEntry R(SectionID, Offset, MachO::ARM64_RELOC_SUBTRACTOR, (uint64_t)Addend,511 SectionAID, SectionAOffset, SectionBID, SectionBOffset,512 false, Size);513 514 addRelocationForSection(R, SectionAID);515 516 return ++RelI;517 }518 519 static const char *getRelocName(uint32_t RelocType) {520 switch (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";532 }533 return "Unrecognized arm64 addend";534 }535 536};537}538 539#undef DEBUG_TYPE540 541#endif542