]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / ExecutionEngine / RuntimeDyld / Targets / RuntimeDyldMachOAArch64.h
1 //===-- RuntimeDyldMachOAArch64.h -- MachO/AArch64 specific code. -*- C++ -*-=//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
11 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
12
13 #include "../RuntimeDyldMachO.h"
14 #include "llvm/Support/Endian.h"
15
16 #define DEBUG_TYPE "dyld"
17
18 namespace llvm {
19
20 class RuntimeDyldMachOAArch64
21     : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOAArch64> {
22 public:
23
24   typedef uint64_t TargetPtrT;
25
26   RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM,
27                           JITSymbolResolver &Resolver)
28       : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
29
30   unsigned getMaxStubSize() override { return 8; }
31
32   unsigned getStubAlignment() override { return 8; }
33
34   /// Extract the addend encoded in the instruction / memory location.
35   Expected<int64_t> decodeAddend(const RelocationEntry &RE) const {
36     const SectionEntry &Section = Sections[RE.SectionID];
37     uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
38     unsigned NumBytes = 1 << RE.Size;
39     int64_t Addend = 0;
40     // Verify that the relocation has the correct size and alignment.
41     switch (RE.RelType) {
42     default: {
43       std::string ErrMsg;
44       {
45         raw_string_ostream ErrStream(ErrMsg);
46         ErrStream << "Unsupported relocation type: "
47                   << getRelocName(RE.RelType);
48       }
49       return make_error<StringError>(std::move(ErrMsg),
50                                      inconvertibleErrorCode());
51     }
52     case MachO::ARM64_RELOC_POINTER_TO_GOT:
53     case MachO::ARM64_RELOC_UNSIGNED: {
54       if (NumBytes != 4 && NumBytes != 8) {
55         std::string ErrMsg;
56         {
57           raw_string_ostream ErrStream(ErrMsg);
58           ErrStream << "Invalid relocation size for relocation "
59                     << getRelocName(RE.RelType);
60         }
61         return make_error<StringError>(std::move(ErrMsg),
62                                        inconvertibleErrorCode());
63       }
64       break;
65     }
66     case MachO::ARM64_RELOC_BRANCH26:
67     case MachO::ARM64_RELOC_PAGE21:
68     case MachO::ARM64_RELOC_PAGEOFF12:
69     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
70     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
71       assert(NumBytes == 4 && "Invalid relocation size.");
72       assert((((uintptr_t)LocalAddress & 0x3) == 0) &&
73              "Instruction address is not aligned to 4 bytes.");
74       break;
75     }
76
77     switch (RE.RelType) {
78     default:
79       llvm_unreachable("Unsupported relocation type!");
80     case MachO::ARM64_RELOC_POINTER_TO_GOT:
81     case MachO::ARM64_RELOC_UNSIGNED:
82       // This could be an unaligned memory location.
83       if (NumBytes == 4)
84         Addend = *reinterpret_cast<support::ulittle32_t *>(LocalAddress);
85       else
86         Addend = *reinterpret_cast<support::ulittle64_t *>(LocalAddress);
87       break;
88     case MachO::ARM64_RELOC_BRANCH26: {
89       // Verify that the relocation points to a B/BL instruction.
90       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
91       assert(((*p & 0xFC000000) == 0x14000000 ||
92               (*p & 0xFC000000) == 0x94000000) &&
93              "Expected branch instruction.");
94
95       // Get the 26 bit addend encoded in the branch instruction and sign-extend
96       // to 64 bit. The lower 2 bits are always zeros and are therefore implicit
97       // (<< 2).
98       Addend = (*p & 0x03FFFFFF) << 2;
99       Addend = SignExtend64(Addend, 28);
100       break;
101     }
102     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
103     case MachO::ARM64_RELOC_PAGE21: {
104       // Verify that the relocation points to the expected adrp instruction.
105       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
106       assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
107
108       // Get the 21 bit addend encoded in the adrp instruction and sign-extend
109       // to 64 bit. The lower 12 bits (4096 byte page) are always zeros and are
110       // therefore implicit (<< 12).
111       Addend = ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3) << 12;
112       Addend = SignExtend64(Addend, 33);
113       break;
114     }
115     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
116       // Verify that the relocation points to one of the expected load / store
117       // instructions.
118       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
119       (void)p;
120       assert((*p & 0x3B000000) == 0x39000000 &&
121              "Only expected load / store instructions.");
122       LLVM_FALLTHROUGH;
123     }
124     case MachO::ARM64_RELOC_PAGEOFF12: {
125       // Verify that the relocation points to one of the expected load / store
126       // or add / sub instructions.
127       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
128       assert((((*p & 0x3B000000) == 0x39000000) ||
129               ((*p & 0x11C00000) == 0x11000000)   ) &&
130              "Expected load / store  or add/sub instruction.");
131
132       // Get the 12 bit addend encoded in the instruction.
133       Addend = (*p & 0x003FFC00) >> 10;
134
135       // Check which instruction we are decoding to obtain the implicit shift
136       // factor of the instruction.
137       int ImplicitShift = 0;
138       if ((*p & 0x3B000000) == 0x39000000) { // << load / store
139         // For load / store instructions the size is encoded in bits 31:30.
140         ImplicitShift = ((*p >> 30) & 0x3);
141         if (ImplicitShift == 0) {
142           // Check if this a vector op to get the correct shift value.
143           if ((*p & 0x04800000) == 0x04800000)
144             ImplicitShift = 4;
145         }
146       }
147       // Compensate for implicit shift.
148       Addend <<= ImplicitShift;
149       break;
150     }
151     }
152     return Addend;
153   }
154
155   /// Extract the addend encoded in the instruction.
156   void encodeAddend(uint8_t *LocalAddress, unsigned NumBytes,
157                     MachO::RelocationInfoType RelType, int64_t Addend) const {
158     // Verify that the relocation has the correct alignment.
159     switch (RelType) {
160     default:
161       llvm_unreachable("Unsupported relocation type!");
162     case MachO::ARM64_RELOC_POINTER_TO_GOT:
163     case MachO::ARM64_RELOC_UNSIGNED:
164       assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size.");
165       break;
166     case MachO::ARM64_RELOC_BRANCH26:
167     case MachO::ARM64_RELOC_PAGE21:
168     case MachO::ARM64_RELOC_PAGEOFF12:
169     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
170     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
171       assert(NumBytes == 4 && "Invalid relocation size.");
172       assert((((uintptr_t)LocalAddress & 0x3) == 0) &&
173              "Instruction address is not aligned to 4 bytes.");
174       break;
175     }
176
177     switch (RelType) {
178     default:
179       llvm_unreachable("Unsupported relocation type!");
180     case MachO::ARM64_RELOC_POINTER_TO_GOT:
181     case MachO::ARM64_RELOC_UNSIGNED:
182       // This could be an unaligned memory location.
183       if (NumBytes == 4)
184         *reinterpret_cast<support::ulittle32_t *>(LocalAddress) = Addend;
185       else
186         *reinterpret_cast<support::ulittle64_t *>(LocalAddress) = Addend;
187       break;
188     case MachO::ARM64_RELOC_BRANCH26: {
189       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
190       // Verify that the relocation points to the expected branch instruction.
191       assert(((*p & 0xFC000000) == 0x14000000 ||
192               (*p & 0xFC000000) == 0x94000000) &&
193              "Expected branch instruction.");
194
195       // Verify addend value.
196       assert((Addend & 0x3) == 0 && "Branch target is not aligned");
197       assert(isInt<28>(Addend) && "Branch target is out of range.");
198
199       // Encode the addend as 26 bit immediate in the branch instruction.
200       *p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF);
201       break;
202     }
203     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
204     case MachO::ARM64_RELOC_PAGE21: {
205       // Verify that the relocation points to the expected adrp instruction.
206       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
207       assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
208
209       // Check that the addend fits into 21 bits (+ 12 lower bits).
210       assert((Addend & 0xFFF) == 0 && "ADRP target is not page aligned.");
211       assert(isInt<33>(Addend) && "Invalid page reloc value.");
212
213       // Encode the addend into the instruction.
214       uint32_t ImmLoValue = ((uint64_t)Addend << 17) & 0x60000000;
215       uint32_t ImmHiValue = ((uint64_t)Addend >> 9) & 0x00FFFFE0;
216       *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue;
217       break;
218     }
219     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
220       // Verify that the relocation points to one of the expected load / store
221       // instructions.
222       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
223       assert((*p & 0x3B000000) == 0x39000000 &&
224              "Only expected load / store instructions.");
225       (void)p;
226       LLVM_FALLTHROUGH;
227     }
228     case MachO::ARM64_RELOC_PAGEOFF12: {
229       // Verify that the relocation points to one of the expected load / store
230       // or add / sub instructions.
231       auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
232       assert((((*p & 0x3B000000) == 0x39000000) ||
233               ((*p & 0x11C00000) == 0x11000000)   ) &&
234              "Expected load / store  or add/sub instruction.");
235
236       // Check which instruction we are decoding to obtain the implicit shift
237       // factor of the instruction and verify alignment.
238       int ImplicitShift = 0;
239       if ((*p & 0x3B000000) == 0x39000000) { // << load / store
240         // For load / store instructions the size is encoded in bits 31:30.
241         ImplicitShift = ((*p >> 30) & 0x3);
242         switch (ImplicitShift) {
243         case 0:
244           // Check if this a vector op to get the correct shift value.
245           if ((*p & 0x04800000) == 0x04800000) {
246             ImplicitShift = 4;
247             assert(((Addend & 0xF) == 0) &&
248                    "128-bit LDR/STR not 16-byte aligned.");
249           }
250           break;
251         case 1:
252           assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned.");
253           break;
254         case 2:
255           assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned.");
256           break;
257         case 3:
258           assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned.");
259           break;
260         }
261       }
262       // Compensate for implicit shift.
263       Addend >>= ImplicitShift;
264       assert(isUInt<12>(Addend) && "Addend cannot be encoded.");
265
266       // Encode the addend into the instruction.
267       *p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00);
268       break;
269     }
270     }
271   }
272
273   Expected<relocation_iterator>
274   processRelocationRef(unsigned SectionID, relocation_iterator RelI,
275                        const ObjectFile &BaseObjT,
276                        ObjSectionToIDMap &ObjSectionToID,
277                        StubMap &Stubs) override {
278     const MachOObjectFile &Obj =
279       static_cast<const MachOObjectFile &>(BaseObjT);
280     MachO::any_relocation_info RelInfo =
281         Obj.getRelocation(RelI->getRawDataRefImpl());
282
283     if (Obj.isRelocationScattered(RelInfo))
284       return make_error<RuntimeDyldError>("Scattered relocations not supported "
285                                           "for MachO AArch64");
286
287     // ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit
288     // addend for the following relocation. If found: (1) store the associated
289     // addend, (2) consume the next relocation, and (3) use the stored addend to
290     // override the addend.
291     int64_t ExplicitAddend = 0;
292     if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_ADDEND) {
293       assert(!Obj.getPlainRelocationExternal(RelInfo));
294       assert(!Obj.getAnyRelocationPCRel(RelInfo));
295       assert(Obj.getAnyRelocationLength(RelInfo) == 2);
296       int64_t RawAddend = Obj.getPlainRelocationSymbolNum(RelInfo);
297       // Sign-extend the 24-bit to 64-bit.
298       ExplicitAddend = SignExtend64(RawAddend, 24);
299       ++RelI;
300       RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());
301     }
302
303     if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_SUBTRACTOR)
304       return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID);
305
306     RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
307
308     if (RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT) {
309       bool Valid =
310           (RE.Size == 2 && RE.IsPCRel) || (RE.Size == 3 && !RE.IsPCRel);
311       if (!Valid)
312         return make_error<StringError>("ARM64_RELOC_POINTER_TO_GOT supports "
313                                        "32-bit pc-rel or 64-bit absolute only",
314                                        inconvertibleErrorCode());
315     }
316
317     if (auto Addend = decodeAddend(RE))
318       RE.Addend = *Addend;
319     else
320       return Addend.takeError();
321
322     assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\
323       "ARM64_RELOC_ADDEND and embedded addend in the instruction.");
324     if (ExplicitAddend)
325       RE.Addend = ExplicitAddend;
326
327     RelocationValueRef Value;
328     if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
329       Value = *ValueOrErr;
330     else
331       return ValueOrErr.takeError();
332
333     bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
334     if (RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT) {
335       // We'll take care of the offset in processGOTRelocation.
336       Value.Offset = 0;
337     } else if (!IsExtern && RE.IsPCRel)
338       makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
339
340     RE.Addend = Value.Offset;
341
342     if (RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGE21 ||
343         RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12 ||
344         RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT)
345       processGOTRelocation(RE, Value, Stubs);
346     else {
347       if (Value.SymbolName)
348         addRelocationForSymbol(RE, Value.SymbolName);
349       else
350         addRelocationForSection(RE, Value.SectionID);
351     }
352
353     return ++RelI;
354   }
355
356   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
357     LLVM_DEBUG(dumpRelocationToResolve(RE, Value));
358
359     const SectionEntry &Section = Sections[RE.SectionID];
360     uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
361     MachO::RelocationInfoType RelType =
362       static_cast<MachO::RelocationInfoType>(RE.RelType);
363
364     switch (RelType) {
365     default:
366       llvm_unreachable("Invalid relocation type!");
367     case MachO::ARM64_RELOC_UNSIGNED: {
368       assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_UNSIGNED not supported");
369       // Mask in the target value a byte at a time (we don't have an alignment
370       // guarantee for the target address, so this is safest).
371       if (RE.Size < 2)
372         llvm_unreachable("Invalid size for ARM64_RELOC_UNSIGNED");
373
374       encodeAddend(LocalAddress, 1 << RE.Size, RelType, Value + RE.Addend);
375       break;
376     }
377
378     case MachO::ARM64_RELOC_POINTER_TO_GOT: {
379       assert(((RE.Size == 2 && RE.IsPCRel) || (RE.Size == 3 && !RE.IsPCRel)) &&
380              "ARM64_RELOC_POINTER_TO_GOT only supports 32-bit pc-rel or 64-bit "
381              "absolute");
382       // Addend is the GOT entry address and RE.Offset the target of the
383       // relocation.
384       uint64_t Result =
385           RE.IsPCRel ? (RE.Addend - RE.Offset) : (Value + RE.Addend);
386       encodeAddend(LocalAddress, 1 << RE.Size, RelType, Result);
387       break;
388     }
389
390     case MachO::ARM64_RELOC_BRANCH26: {
391       assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_BRANCH26 not supported");
392       // Check if branch is in range.
393       uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
394       int64_t PCRelVal = Value - FinalAddress + RE.Addend;
395       encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal);
396       break;
397     }
398     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
399     case MachO::ARM64_RELOC_PAGE21: {
400       assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_PAGE21 not supported");
401       // Adjust for PC-relative relocation and offset.
402       uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
403       int64_t PCRelVal =
404         ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));
405       encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal);
406       break;
407     }
408     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
409     case MachO::ARM64_RELOC_PAGEOFF12: {
410       assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_PAGEOFF21 not supported");
411       // Add the offset from the symbol.
412       Value += RE.Addend;
413       // Mask out the page address and only use the lower 12 bits.
414       Value &= 0xFFF;
415       encodeAddend(LocalAddress, /*Size=*/4, RelType, Value);
416       break;
417     }
418     case MachO::ARM64_RELOC_SUBTRACTOR: {
419       uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
420       uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
421       assert((Value == SectionABase || Value == SectionBBase) &&
422              "Unexpected SUBTRACTOR relocation value.");
423       Value = SectionABase - SectionBBase + RE.Addend;
424       writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
425       break;
426     }
427
428     case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
429     case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
430       llvm_unreachable("Relocation type not yet implemented!");
431     case MachO::ARM64_RELOC_ADDEND:
432       llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by "
433                        "processRelocationRef!");
434     }
435   }
436
437   Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
438                        const SectionRef &Section) {
439     return Error::success();
440   }
441
442 private:
443   void processGOTRelocation(const RelocationEntry &RE,
444                             RelocationValueRef &Value, StubMap &Stubs) {
445     assert((RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT &&
446             (RE.Size == 2 || RE.Size == 3)) ||
447            RE.Size == 2);
448     SectionEntry &Section = Sections[RE.SectionID];
449     StubMap::const_iterator i = Stubs.find(Value);
450     int64_t Offset;
451     if (i != Stubs.end())
452       Offset = static_cast<int64_t>(i->second);
453     else {
454       // FIXME: There must be a better way to do this then to check and fix the
455       // alignment every time!!!
456       uintptr_t BaseAddress = uintptr_t(Section.getAddress());
457       uintptr_t StubAlignment = getStubAlignment();
458       uintptr_t StubAddress =
459           (BaseAddress + Section.getStubOffset() + StubAlignment - 1) &
460           -StubAlignment;
461       unsigned StubOffset = StubAddress - BaseAddress;
462       Stubs[Value] = StubOffset;
463       assert(((StubAddress % getStubAlignment()) == 0) &&
464              "GOT entry not aligned");
465       RelocationEntry GOTRE(RE.SectionID, StubOffset,
466                             MachO::ARM64_RELOC_UNSIGNED, Value.Offset,
467                             /*IsPCRel=*/false, /*Size=*/3);
468       if (Value.SymbolName)
469         addRelocationForSymbol(GOTRE, Value.SymbolName);
470       else
471         addRelocationForSection(GOTRE, Value.SectionID);
472       Section.advanceStubOffset(getMaxStubSize());
473       Offset = static_cast<int64_t>(StubOffset);
474     }
475     RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, Offset,
476                              RE.IsPCRel, RE.Size);
477     addRelocationForSection(TargetRE, RE.SectionID);
478   }
479
480   Expected<relocation_iterator>
481   processSubtractRelocation(unsigned SectionID, relocation_iterator RelI,
482                             const ObjectFile &BaseObjT,
483                             ObjSectionToIDMap &ObjSectionToID) {
484     const MachOObjectFile &Obj =
485         static_cast<const MachOObjectFile&>(BaseObjT);
486     MachO::any_relocation_info RE =
487         Obj.getRelocation(RelI->getRawDataRefImpl());
488
489     unsigned Size = Obj.getAnyRelocationLength(RE);
490     uint64_t Offset = RelI->getOffset();
491     uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset);
492     unsigned NumBytes = 1 << Size;
493
494     Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName();
495     if (!SubtrahendNameOrErr)
496       return SubtrahendNameOrErr.takeError();
497     auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr);
498     unsigned SectionBID = SubtrahendI->second.getSectionID();
499     uint64_t SectionBOffset = SubtrahendI->second.getOffset();
500     int64_t Addend =
501       SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8);
502
503     ++RelI;
504     Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName();
505     if (!MinuendNameOrErr)
506       return MinuendNameOrErr.takeError();
507     auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr);
508     unsigned SectionAID = MinuendI->second.getSectionID();
509     uint64_t SectionAOffset = MinuendI->second.getOffset();
510
511     RelocationEntry R(SectionID, Offset, MachO::ARM64_RELOC_SUBTRACTOR, (uint64_t)Addend,
512                       SectionAID, SectionAOffset, SectionBID, SectionBOffset,
513                       false, Size);
514
515     addRelocationForSection(R, SectionAID);
516
517     return ++RelI;
518   }
519
520   static const char *getRelocName(uint32_t RelocType) {
521     switch (RelocType) {
522       case MachO::ARM64_RELOC_UNSIGNED: return "ARM64_RELOC_UNSIGNED";
523       case MachO::ARM64_RELOC_SUBTRACTOR: return "ARM64_RELOC_SUBTRACTOR";
524       case MachO::ARM64_RELOC_BRANCH26: return "ARM64_RELOC_BRANCH26";
525       case MachO::ARM64_RELOC_PAGE21: return "ARM64_RELOC_PAGE21";
526       case MachO::ARM64_RELOC_PAGEOFF12: return "ARM64_RELOC_PAGEOFF12";
527       case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: return "ARM64_RELOC_GOT_LOAD_PAGE21";
528       case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: return "ARM64_RELOC_GOT_LOAD_PAGEOFF12";
529       case MachO::ARM64_RELOC_POINTER_TO_GOT: return "ARM64_RELOC_POINTER_TO_GOT";
530       case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: return "ARM64_RELOC_TLVP_LOAD_PAGE21";
531       case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: return "ARM64_RELOC_TLVP_LOAD_PAGEOFF12";
532       case MachO::ARM64_RELOC_ADDEND: return "ARM64_RELOC_ADDEND";
533     }
534     return "Unrecognized arm64 addend";
535   }
536
537 };
538 }
539
540 #undef DEBUG_TYPE
541
542 #endif