]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / lib / ReaderWriter / MachO / ArchHandler_arm64.cpp
1 //===- lib/FileFormat/MachO/ArchHandler_arm64.cpp -------------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ArchHandler.h"
10 #include "Atoms.h"
11 #include "MachONormalizedFileBinaryUtils.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/Support/Endian.h"
16 #include "llvm/Support/ErrorHandling.h"
17 #include "llvm/Support/Format.h"
18
19 using namespace llvm::MachO;
20 using namespace lld::mach_o::normalized;
21
22 namespace lld {
23 namespace mach_o {
24
25 using llvm::support::ulittle32_t;
26 using llvm::support::ulittle64_t;
27
28 using llvm::support::little32_t;
29 using llvm::support::little64_t;
30
31 class ArchHandler_arm64 : public ArchHandler {
32 public:
33   ArchHandler_arm64() = default;
34   ~ArchHandler_arm64() override = default;
35
36   const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
37
38   Reference::KindArch kindArch() override {
39     return Reference::KindArch::AArch64;
40   }
41
42   /// Used by GOTPass to locate GOT References
43   bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
44     if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
45       return false;
46     assert(ref.kindArch() == Reference::KindArch::AArch64);
47     switch (ref.kindValue()) {
48     case gotPage21:
49     case gotOffset12:
50       canBypassGOT = true;
51       return true;
52     case delta32ToGOT:
53     case unwindCIEToPersonalityFunction:
54     case imageOffsetGot:
55       canBypassGOT = false;
56       return true;
57     default:
58       return false;
59     }
60   }
61
62   /// Used by GOTPass to update GOT References.
63   void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
64     // If GOT slot was instanciated, transform:
65     //   gotPage21/gotOffset12 -> page21/offset12scale8
66     // If GOT slot optimized away, transform:
67     //   gotPage21/gotOffset12 -> page21/addOffset12
68     assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
69     assert(ref->kindArch() == Reference::KindArch::AArch64);
70     switch (ref->kindValue()) {
71     case gotPage21:
72       const_cast<Reference *>(ref)->setKindValue(page21);
73       break;
74     case gotOffset12:
75       const_cast<Reference *>(ref)->setKindValue(targetNowGOT ?
76                                                  offset12scale8 : addOffset12);
77       break;
78     case delta32ToGOT:
79       const_cast<Reference *>(ref)->setKindValue(delta32);
80       break;
81     case imageOffsetGot:
82       const_cast<Reference *>(ref)->setKindValue(imageOffset);
83       break;
84     default:
85       llvm_unreachable("Not a GOT reference");
86     }
87   }
88
89   const StubInfo &stubInfo() override { return _sStubInfo; }
90
91   bool isCallSite(const Reference &) override;
92   bool isNonCallBranch(const Reference &) override {
93     return false;
94   }
95
96   bool isPointer(const Reference &) override;
97   bool isPairedReloc(const normalized::Relocation &) override;
98
99   bool needsCompactUnwind() override {
100     return true;
101   }
102   Reference::KindValue imageOffsetKind() override {
103     return imageOffset;
104   }
105   Reference::KindValue imageOffsetKindIndirect() override {
106     return imageOffsetGot;
107   }
108
109   Reference::KindValue unwindRefToPersonalityFunctionKind() override {
110     return unwindCIEToPersonalityFunction;
111   }
112
113   Reference::KindValue unwindRefToCIEKind() override {
114     return negDelta32;
115   }
116
117   Reference::KindValue unwindRefToFunctionKind() override {
118     return unwindFDEToFunction;
119   }
120
121   Reference::KindValue unwindRefToEhFrameKind() override {
122     return unwindInfoToEhFrame;
123   }
124
125   Reference::KindValue pointerKind() override {
126     return pointer64;
127   }
128
129   Reference::KindValue lazyImmediateLocationKind() override {
130     return lazyImmediateLocation;
131   }
132
133   uint32_t dwarfCompactUnwindType() override {
134     return 0x03000000;
135   }
136
137   llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
138                                const DefinedAtom *inAtom,
139                                uint32_t offsetInAtom,
140                                uint64_t fixupAddress, bool isBig,
141                                FindAtomBySectionAndAddress atomFromAddress,
142                                FindAtomBySymbolIndex atomFromSymbolIndex,
143                                Reference::KindValue *kind,
144                                const lld::Atom **target,
145                                Reference::Addend *addend) override;
146   llvm::Error
147       getPairReferenceInfo(const normalized::Relocation &reloc1,
148                            const normalized::Relocation &reloc2,
149                            const DefinedAtom *inAtom,
150                            uint32_t offsetInAtom,
151                            uint64_t fixupAddress, bool isBig, bool scatterable,
152                            FindAtomBySectionAndAddress atomFromAddress,
153                            FindAtomBySymbolIndex atomFromSymbolIndex,
154                            Reference::KindValue *kind,
155                            const lld::Atom **target,
156                            Reference::Addend *addend) override;
157
158   bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override {
159     return (atom->contentType() == DefinedAtom::typeCString);
160   }
161
162   void generateAtomContent(const DefinedAtom &atom, bool relocatable,
163                            FindAddressForAtom findAddress,
164                            FindAddressForAtom findSectionAddress,
165                            uint64_t imageBaseAddress,
166                     llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
167
168   void appendSectionRelocations(const DefinedAtom &atom,
169                                 uint64_t atomSectionOffset,
170                                 const Reference &ref,
171                                 FindSymbolIndexForAtom symbolIndexForAtom,
172                                 FindSectionIndexForAtom sectionIndexForAtom,
173                                 FindAddressForAtom addressForAtom,
174                                 normalized::Relocations &relocs) override;
175
176 private:
177   static const Registry::KindStrings _sKindStrings[];
178   static const StubInfo _sStubInfo;
179
180   enum Arm64Kind : Reference::KindValue {
181     invalid,               /// for error condition
182
183     // Kinds found in mach-o .o files:
184     branch26,              /// ex: bl   _foo
185     page21,                /// ex: adrp x1, _foo@PAGE
186     offset12,              /// ex: ldrb w0, [x1, _foo@PAGEOFF]
187     offset12scale2,        /// ex: ldrs w0, [x1, _foo@PAGEOFF]
188     offset12scale4,        /// ex: ldr  w0, [x1, _foo@PAGEOFF]
189     offset12scale8,        /// ex: ldr  x0, [x1, _foo@PAGEOFF]
190     offset12scale16,       /// ex: ldr  q0, [x1, _foo@PAGEOFF]
191     gotPage21,             /// ex: adrp x1, _foo@GOTPAGE
192     gotOffset12,           /// ex: ldr  w0, [x1, _foo@GOTPAGEOFF]
193     tlvPage21,             /// ex: adrp x1, _foo@TLVPAGE
194     tlvOffset12,           /// ex: ldr  w0, [x1, _foo@TLVPAGEOFF]
195
196     pointer64,             /// ex: .quad _foo
197     delta64,               /// ex: .quad _foo - .
198     delta32,               /// ex: .long _foo - .
199     negDelta32,            /// ex: .long . - _foo
200     pointer64ToGOT,        /// ex: .quad _foo@GOT
201     delta32ToGOT,          /// ex: .long _foo@GOT - .
202
203     // Kinds introduced by Passes:
204     addOffset12,           /// Location contains LDR to change into ADD.
205     lazyPointer,           /// Location contains a lazy pointer.
206     lazyImmediateLocation, /// Location contains immediate value used in stub.
207     imageOffset,           /// Location contains offset of atom in final image
208     imageOffsetGot,        /// Location contains offset of GOT entry for atom in
209                            /// final image (typically personality function).
210     unwindCIEToPersonalityFunction,   /// Nearly delta32ToGOT, but cannot be
211                            /// rematerialized in relocatable object
212                            /// (yay for implicit contracts!).
213     unwindFDEToFunction,   /// Nearly delta64, but cannot be rematerialized in
214                            /// relocatable object (yay for implicit contracts!).
215     unwindInfoToEhFrame,   /// Fix low 24 bits of compact unwind encoding to
216                            /// refer to __eh_frame entry.
217   };
218
219   void applyFixupFinal(const Reference &ref, uint8_t *location,
220                        uint64_t fixupAddress, uint64_t targetAddress,
221                        uint64_t inAtomAddress, uint64_t imageBaseAddress,
222                        FindAddressForAtom findSectionAddress);
223
224   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
225                              uint64_t fixupAddress, uint64_t targetAddress,
226                              uint64_t inAtomAddress, bool targetUnnamed);
227
228   // Utility functions for inspecting/updating instructions.
229   static uint32_t setDisplacementInBranch26(uint32_t instr, int32_t disp);
230   static uint32_t setDisplacementInADRP(uint32_t instr, int64_t disp);
231   static Arm64Kind offset12KindFromInstruction(uint32_t instr);
232   static uint32_t setImm12(uint32_t instr, uint32_t offset);
233 };
234
235 const Registry::KindStrings ArchHandler_arm64::_sKindStrings[] = {
236   LLD_KIND_STRING_ENTRY(invalid),
237   LLD_KIND_STRING_ENTRY(branch26),
238   LLD_KIND_STRING_ENTRY(page21),
239   LLD_KIND_STRING_ENTRY(offset12),
240   LLD_KIND_STRING_ENTRY(offset12scale2),
241   LLD_KIND_STRING_ENTRY(offset12scale4),
242   LLD_KIND_STRING_ENTRY(offset12scale8),
243   LLD_KIND_STRING_ENTRY(offset12scale16),
244   LLD_KIND_STRING_ENTRY(gotPage21),
245   LLD_KIND_STRING_ENTRY(gotOffset12),
246   LLD_KIND_STRING_ENTRY(tlvPage21),
247   LLD_KIND_STRING_ENTRY(tlvOffset12),
248   LLD_KIND_STRING_ENTRY(pointer64),
249   LLD_KIND_STRING_ENTRY(delta64),
250   LLD_KIND_STRING_ENTRY(delta32),
251   LLD_KIND_STRING_ENTRY(negDelta32),
252   LLD_KIND_STRING_ENTRY(pointer64ToGOT),
253   LLD_KIND_STRING_ENTRY(delta32ToGOT),
254
255   LLD_KIND_STRING_ENTRY(addOffset12),
256   LLD_KIND_STRING_ENTRY(lazyPointer),
257   LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
258   LLD_KIND_STRING_ENTRY(imageOffset),
259   LLD_KIND_STRING_ENTRY(imageOffsetGot),
260   LLD_KIND_STRING_ENTRY(unwindCIEToPersonalityFunction),
261   LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
262   LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
263
264   LLD_KIND_STRING_END
265 };
266
267 const ArchHandler::StubInfo ArchHandler_arm64::_sStubInfo = {
268   "dyld_stub_binder",
269
270   // Lazy pointer references
271   { Reference::KindArch::AArch64, pointer64, 0, 0 },
272   { Reference::KindArch::AArch64, lazyPointer, 0, 0 },
273
274   // GOT pointer to dyld_stub_binder
275   { Reference::KindArch::AArch64, pointer64, 0, 0 },
276
277   // arm64 code alignment 2^1
278   1,
279
280   // Stub size and code
281   12,
282   { 0x10, 0x00, 0x00, 0x90,   // ADRP  X16, lazy_pointer@page
283     0x10, 0x02, 0x40, 0xF9,   // LDR   X16, [X16, lazy_pointer@pageoff]
284     0x00, 0x02, 0x1F, 0xD6 }, // BR    X16
285   { Reference::KindArch::AArch64, page21, 0, 0 },
286   { true,                         offset12scale8, 4, 0 },
287
288   // Stub Helper size and code
289   12,
290   { 0x50, 0x00, 0x00, 0x18,   //      LDR   W16, L0
291     0x00, 0x00, 0x00, 0x14,   //      LDR   B  helperhelper
292     0x00, 0x00, 0x00, 0x00 }, // L0: .long 0
293   { Reference::KindArch::AArch64, lazyImmediateLocation, 8, 0 },
294   { Reference::KindArch::AArch64, branch26, 4, 0 },
295
296   // Stub helper image cache content type
297   DefinedAtom::typeGOT,
298
299   // Stub Helper-Common size and code
300   24,
301   // Stub helper alignment
302   2,
303   { 0x11, 0x00, 0x00, 0x90,   //  ADRP  X17, dyld_ImageLoaderCache@page
304     0x31, 0x02, 0x00, 0x91,   //  ADD   X17, X17, dyld_ImageLoaderCache@pageoff
305     0xF0, 0x47, 0xBF, 0xA9,   //  STP   X16/X17, [SP, #-16]!
306     0x10, 0x00, 0x00, 0x90,   //  ADRP  X16, _fast_lazy_bind@page
307     0x10, 0x02, 0x40, 0xF9,   //  LDR   X16, [X16,_fast_lazy_bind@pageoff]
308     0x00, 0x02, 0x1F, 0xD6 }, //  BR    X16
309   { Reference::KindArch::AArch64, page21,   0, 0 },
310   { true,                         offset12, 4, 0 },
311   { Reference::KindArch::AArch64, page21,   12, 0 },
312   { true,                         offset12scale8, 16, 0 }
313 };
314
315 bool ArchHandler_arm64::isCallSite(const Reference &ref) {
316   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
317     return false;
318   assert(ref.kindArch() == Reference::KindArch::AArch64);
319   return (ref.kindValue() == branch26);
320 }
321
322 bool ArchHandler_arm64::isPointer(const Reference &ref) {
323   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
324     return false;
325   assert(ref.kindArch() == Reference::KindArch::AArch64);
326   Reference::KindValue kind = ref.kindValue();
327   return (kind == pointer64);
328 }
329
330 bool ArchHandler_arm64::isPairedReloc(const Relocation &r) {
331   return ((r.type == ARM64_RELOC_ADDEND) || (r.type == ARM64_RELOC_SUBTRACTOR));
332 }
333
334 uint32_t ArchHandler_arm64::setDisplacementInBranch26(uint32_t instr,
335                                                       int32_t displacement) {
336   assert((displacement <= 134217727) && (displacement > (-134217728)) &&
337          "arm64 branch out of range");
338   return (instr & 0xFC000000) | ((uint32_t)(displacement >> 2) & 0x03FFFFFF);
339 }
340
341 uint32_t ArchHandler_arm64::setDisplacementInADRP(uint32_t instruction,
342                                                   int64_t displacement) {
343   assert((displacement <= 0x100000000LL) && (displacement > (-0x100000000LL)) &&
344          "arm64 ADRP out of range");
345   assert(((instruction & 0x9F000000) == 0x90000000) &&
346          "reloc not on ADRP instruction");
347   uint32_t immhi = (displacement >> 9) & (0x00FFFFE0);
348   uint32_t immlo = (displacement << 17) & (0x60000000);
349   return (instruction & 0x9F00001F) | immlo | immhi;
350 }
351
352 ArchHandler_arm64::Arm64Kind
353 ArchHandler_arm64::offset12KindFromInstruction(uint32_t instruction) {
354   if (instruction & 0x08000000) {
355     switch ((instruction >> 30) & 0x3) {
356     case 0:
357       if ((instruction & 0x04800000) == 0x04800000)
358         return offset12scale16;
359       return offset12;
360     case 1:
361       return offset12scale2;
362     case 2:
363       return offset12scale4;
364     case 3:
365       return offset12scale8;
366     }
367   }
368   return offset12;
369 }
370
371 uint32_t ArchHandler_arm64::setImm12(uint32_t instruction, uint32_t offset) {
372   assert(((offset & 0xFFFFF000) == 0) && "imm12 offset out of range");
373   uint32_t imm12 = offset << 10;
374   return (instruction & 0xFFC003FF) | imm12;
375 }
376
377 llvm::Error ArchHandler_arm64::getReferenceInfo(
378     const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
379     uint64_t fixupAddress, bool isBig,
380     FindAtomBySectionAndAddress atomFromAddress,
381     FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
382     const lld::Atom **target, Reference::Addend *addend) {
383   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
384   switch (relocPattern(reloc)) {
385   case ARM64_RELOC_BRANCH26           | rPcRel | rExtern | rLength4:
386     // ex: bl _foo
387     *kind = branch26;
388     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
389       return ec;
390     *addend = 0;
391     return llvm::Error::success();
392   case ARM64_RELOC_PAGE21             | rPcRel | rExtern | rLength4:
393     // ex: adrp x1, _foo@PAGE
394     *kind = page21;
395     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
396       return ec;
397     *addend = 0;
398     return llvm::Error::success();
399   case ARM64_RELOC_PAGEOFF12                   | rExtern | rLength4:
400     // ex: ldr x0, [x1, _foo@PAGEOFF]
401     *kind = offset12KindFromInstruction(*(const little32_t *)fixupContent);
402     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
403       return ec;
404     *addend = 0;
405     return llvm::Error::success();
406   case ARM64_RELOC_GOT_LOAD_PAGE21    | rPcRel | rExtern | rLength4:
407     // ex: adrp x1, _foo@GOTPAGE
408     *kind = gotPage21;
409     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
410       return ec;
411     *addend = 0;
412     return llvm::Error::success();
413   case ARM64_RELOC_GOT_LOAD_PAGEOFF12          | rExtern | rLength4:
414     // ex: ldr x0, [x1, _foo@GOTPAGEOFF]
415     *kind = gotOffset12;
416     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
417       return ec;
418     *addend = 0;
419     return llvm::Error::success();
420   case ARM64_RELOC_TLVP_LOAD_PAGE21   | rPcRel | rExtern | rLength4:
421     // ex: adrp x1, _foo@TLVPAGE
422     *kind = tlvPage21;
423     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
424       return ec;
425     *addend = 0;
426     return llvm::Error::success();
427   case ARM64_RELOC_TLVP_LOAD_PAGEOFF12         | rExtern | rLength4:
428     // ex: ldr x0, [x1, _foo@TLVPAGEOFF]
429     *kind = tlvOffset12;
430     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
431       return ec;
432     *addend = 0;
433     return llvm::Error::success();
434   case ARM64_RELOC_UNSIGNED                    | rExtern | rLength8:
435     // ex: .quad _foo + N
436     *kind = pointer64;
437     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
438       return ec;
439     *addend = *(const little64_t *)fixupContent;
440     return llvm::Error::success();
441   case ARM64_RELOC_UNSIGNED                              | rLength8:
442      // ex: .quad Lfoo + N
443      *kind = pointer64;
444      return atomFromAddress(reloc.symbol, *(const little64_t *)fixupContent,
445                             target, addend);
446   case ARM64_RELOC_POINTER_TO_GOT              | rExtern | rLength8:
447     // ex: .quad _foo@GOT
448     *kind = pointer64ToGOT;
449     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
450       return ec;
451     *addend = 0;
452     return llvm::Error::success();
453   case ARM64_RELOC_POINTER_TO_GOT     | rPcRel | rExtern | rLength4:
454     // ex: .long _foo@GOT - .
455
456     // If we are in an .eh_frame section, then the kind of the relocation should
457     // not be delta32ToGOT.  It may instead be unwindCIEToPersonalityFunction.
458     if (inAtom->contentType() == DefinedAtom::typeCFI)
459       *kind = unwindCIEToPersonalityFunction;
460     else
461       *kind = delta32ToGOT;
462
463     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
464       return ec;
465     *addend = 0;
466     return llvm::Error::success();
467   default:
468     return llvm::make_error<GenericError>("unsupported arm64 relocation type");
469   }
470 }
471
472 llvm::Error ArchHandler_arm64::getPairReferenceInfo(
473     const normalized::Relocation &reloc1, const normalized::Relocation &reloc2,
474     const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress,
475     bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress,
476     FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
477     const lld::Atom **target, Reference::Addend *addend) {
478   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
479   switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
480   case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
481          ARM64_RELOC_BRANCH26           | rPcRel | rExtern | rLength4):
482     // ex: bl _foo+8
483     *kind = branch26;
484     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
485       return ec;
486     *addend = reloc1.symbol;
487     return llvm::Error::success();
488   case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
489          ARM64_RELOC_PAGE21             | rPcRel | rExtern | rLength4):
490     // ex: adrp x1, _foo@PAGE
491     *kind = page21;
492     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
493       return ec;
494     *addend = reloc1.symbol;
495     return llvm::Error::success();
496   case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
497          ARM64_RELOC_PAGEOFF12                   | rExtern | rLength4): {
498     // ex: ldr w0, [x1, _foo@PAGEOFF]
499     uint32_t cont32 = (int32_t)*(const little32_t *)fixupContent;
500     *kind = offset12KindFromInstruction(cont32);
501     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
502       return ec;
503     *addend = reloc1.symbol;
504     return llvm::Error::success();
505   }
506   case ((ARM64_RELOC_SUBTRACTOR                  | rExtern | rLength8) << 16 |
507          ARM64_RELOC_UNSIGNED                    | rExtern | rLength8):
508     // ex: .quad _foo - .
509     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
510       return ec;
511
512     // If we are in an .eh_frame section, then the kind of the relocation should
513     // not be delta64.  It may instead be unwindFDEToFunction.
514     if (inAtom->contentType() == DefinedAtom::typeCFI)
515       *kind = unwindFDEToFunction;
516     else
517       *kind = delta64;
518
519     // The offsets of the 2 relocations must match
520     if (reloc1.offset != reloc2.offset)
521       return llvm::make_error<GenericError>(
522                                     "paired relocs must have the same offset");
523     *addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
524     return llvm::Error::success();
525   case ((ARM64_RELOC_SUBTRACTOR                  | rExtern | rLength4) << 16 |
526          ARM64_RELOC_UNSIGNED                    | rExtern | rLength4):
527     // ex: .quad _foo - .
528     *kind = delta32;
529     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
530       return ec;
531     *addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
532     return llvm::Error::success();
533   default:
534     return llvm::make_error<GenericError>("unsupported arm64 relocation pair");
535   }
536 }
537
538 void ArchHandler_arm64::generateAtomContent(
539     const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
540     FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
541     llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
542   // Copy raw bytes.
543   std::copy(atom.rawContent().begin(), atom.rawContent().end(),
544             atomContentBuffer.begin());
545   // Apply fix-ups.
546 #ifndef NDEBUG
547   if (atom.begin() != atom.end()) {
548     DEBUG_WITH_TYPE("atom-content", llvm::dbgs()
549                     << "Applying fixups to atom:\n"
550                     << "   address="
551                     << llvm::format("    0x%09lX", &atom)
552                     << ", file=#"
553                     << atom.file().ordinal()
554                     << ", atom=#"
555                     << atom.ordinal()
556                     << ", name="
557                     << atom.name()
558                     << ", type="
559                     << atom.contentType()
560                     << "\n");
561   }
562 #endif
563   for (const Reference *ref : atom) {
564     uint32_t offset = ref->offsetInAtom();
565     const Atom *target = ref->target();
566     bool targetUnnamed = target->name().empty();
567     uint64_t targetAddress = 0;
568     if (isa<DefinedAtom>(target))
569       targetAddress = findAddress(*target);
570     uint64_t atomAddress = findAddress(atom);
571     uint64_t fixupAddress = atomAddress + offset;
572     if (relocatable) {
573       applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
574                             targetAddress, atomAddress, targetUnnamed);
575     } else {
576       applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
577                       targetAddress, atomAddress, imageBaseAddress,
578                       findSectionAddress);
579     }
580   }
581 }
582
583 void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *loc,
584                                         uint64_t fixupAddress,
585                                         uint64_t targetAddress,
586                                         uint64_t inAtomAddress,
587                                         uint64_t imageBaseAddress,
588                                         FindAddressForAtom findSectionAddress) {
589   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
590     return;
591   assert(ref.kindArch() == Reference::KindArch::AArch64);
592   ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
593   ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
594   int32_t displacement;
595   uint32_t instruction;
596   uint32_t value32;
597   uint32_t value64;
598   switch (static_cast<Arm64Kind>(ref.kindValue())) {
599   case branch26:
600     displacement = (targetAddress - fixupAddress) + ref.addend();
601     *loc32 = setDisplacementInBranch26(*loc32, displacement);
602     return;
603   case page21:
604   case gotPage21:
605   case tlvPage21:
606     displacement =
607         ((targetAddress + ref.addend()) & (-4096)) - (fixupAddress & (-4096));
608     *loc32 = setDisplacementInADRP(*loc32, displacement);
609     return;
610   case offset12:
611   case gotOffset12:
612   case tlvOffset12:
613     displacement = (targetAddress + ref.addend()) & 0x00000FFF;
614     *loc32 = setImm12(*loc32, displacement);
615     return;
616   case offset12scale2:
617     displacement = (targetAddress + ref.addend()) & 0x00000FFF;
618     assert(((displacement & 0x1) == 0) &&
619            "scaled imm12 not accessing 2-byte aligneds");
620     *loc32 = setImm12(*loc32, displacement >> 1);
621     return;
622   case offset12scale4:
623     displacement = (targetAddress + ref.addend()) & 0x00000FFF;
624     assert(((displacement & 0x3) == 0) &&
625            "scaled imm12 not accessing 4-byte aligned");
626     *loc32 = setImm12(*loc32, displacement >> 2);
627     return;
628   case offset12scale8:
629     displacement = (targetAddress + ref.addend()) & 0x00000FFF;
630     assert(((displacement & 0x7) == 0) &&
631            "scaled imm12 not accessing 8-byte aligned");
632     *loc32 = setImm12(*loc32, displacement >> 3);
633     return;
634   case offset12scale16:
635     displacement = (targetAddress + ref.addend()) & 0x00000FFF;
636     assert(((displacement & 0xF) == 0) &&
637            "scaled imm12 not accessing 16-byte aligned");
638     *loc32 = setImm12(*loc32, displacement >> 4);
639     return;
640   case addOffset12:
641     instruction = *loc32;
642     assert(((instruction & 0xFFC00000) == 0xF9400000) &&
643            "GOT reloc is not an LDR instruction");
644     displacement = (targetAddress + ref.addend()) & 0x00000FFF;
645     value32 = 0x91000000 | (instruction & 0x000003FF);
646     instruction = setImm12(value32, displacement);
647     *loc32 = instruction;
648     return;
649   case pointer64:
650   case pointer64ToGOT:
651     *loc64 = targetAddress + ref.addend();
652     return;
653   case delta64:
654   case unwindFDEToFunction:
655     *loc64 = (targetAddress - fixupAddress) + ref.addend();
656     return;
657   case delta32:
658   case delta32ToGOT:
659   case unwindCIEToPersonalityFunction:
660     *loc32 = (targetAddress - fixupAddress) + ref.addend();
661     return;
662   case negDelta32:
663     *loc32 = fixupAddress - targetAddress + ref.addend();
664     return;
665   case lazyPointer:
666     // Do nothing
667     return;
668   case lazyImmediateLocation:
669     *loc32 = ref.addend();
670     return;
671   case imageOffset:
672     *loc32 = (targetAddress - imageBaseAddress) + ref.addend();
673     return;
674   case imageOffsetGot:
675     llvm_unreachable("imageOffsetGot should have been changed to imageOffset");
676     break;
677   case unwindInfoToEhFrame:
678     value64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
679     assert(value64 < 0xffffffU && "offset in __eh_frame too large");
680     *loc32 = (*loc32 & 0xff000000U) | value64;
681     return;
682   case invalid:
683     // Fall into llvm_unreachable().
684     break;
685   }
686   llvm_unreachable("invalid arm64 Reference Kind");
687 }
688
689 void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
690                                               uint8_t *loc,
691                                               uint64_t fixupAddress,
692                                               uint64_t targetAddress,
693                                               uint64_t inAtomAddress,
694                                               bool targetUnnamed) {
695   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
696     return;
697   assert(ref.kindArch() == Reference::KindArch::AArch64);
698   ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
699   ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
700   switch (static_cast<Arm64Kind>(ref.kindValue())) {
701   case branch26:
702     *loc32 = setDisplacementInBranch26(*loc32, 0);
703     return;
704   case page21:
705   case gotPage21:
706   case tlvPage21:
707     *loc32 = setDisplacementInADRP(*loc32, 0);
708     return;
709   case offset12:
710   case offset12scale2:
711   case offset12scale4:
712   case offset12scale8:
713   case offset12scale16:
714   case gotOffset12:
715   case tlvOffset12:
716     *loc32 = setImm12(*loc32, 0);
717     return;
718   case pointer64:
719     if (targetUnnamed)
720       *loc64 = targetAddress + ref.addend();
721     else
722       *loc64 = ref.addend();
723     return;
724   case delta64:
725     *loc64 = ref.addend() + inAtomAddress - fixupAddress;
726     return;
727   case unwindFDEToFunction:
728     // We don't emit unwindFDEToFunction in -r mode as they are implicitly
729     // generated from the data in the __eh_frame section.  So here we need
730     // to use the targetAddress so that we can generate the full relocation
731     // when we parse again later.
732     *loc64 = targetAddress - fixupAddress;
733     return;
734   case delta32:
735     *loc32 = ref.addend() + inAtomAddress - fixupAddress;
736     return;
737   case negDelta32:
738     // We don't emit negDelta32 in -r mode as they are implicitly
739     // generated from the data in the __eh_frame section.  So here we need
740     // to use the targetAddress so that we can generate the full relocation
741     // when we parse again later.
742     *loc32 = fixupAddress - targetAddress + ref.addend();
743     return;
744   case pointer64ToGOT:
745     *loc64 = 0;
746     return;
747   case delta32ToGOT:
748     *loc32 = inAtomAddress - fixupAddress;
749     return;
750   case unwindCIEToPersonalityFunction:
751     // We don't emit unwindCIEToPersonalityFunction in -r mode as they are
752     // implicitly generated from the data in the __eh_frame section.  So here we
753     // need to use the targetAddress so that we can generate the full relocation
754     // when we parse again later.
755     *loc32 = targetAddress - fixupAddress;
756     return;
757   case addOffset12:
758     llvm_unreachable("lazy reference kind implies GOT pass was run");
759   case lazyPointer:
760   case lazyImmediateLocation:
761     llvm_unreachable("lazy reference kind implies Stubs pass was run");
762   case imageOffset:
763   case imageOffsetGot:
764   case unwindInfoToEhFrame:
765     llvm_unreachable("fixup implies __unwind_info");
766     return;
767   case invalid:
768     // Fall into llvm_unreachable().
769     break;
770   }
771   llvm_unreachable("unknown arm64 Reference Kind");
772 }
773
774 void ArchHandler_arm64::appendSectionRelocations(
775     const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref,
776     FindSymbolIndexForAtom symbolIndexForAtom,
777     FindSectionIndexForAtom sectionIndexForAtom,
778     FindAddressForAtom addressForAtom, normalized::Relocations &relocs) {
779   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
780     return;
781   assert(ref.kindArch() == Reference::KindArch::AArch64);
782   uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
783   switch (static_cast<Arm64Kind>(ref.kindValue())) {
784   case branch26:
785     if (ref.addend()) {
786       appendReloc(relocs, sectionOffset, ref.addend(), 0,
787                   ARM64_RELOC_ADDEND | rLength4);
788       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
789                   ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
790      } else {
791       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
792                   ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
793     }
794     return;
795   case page21:
796     if (ref.addend()) {
797       appendReloc(relocs, sectionOffset, ref.addend(), 0,
798                   ARM64_RELOC_ADDEND | rLength4);
799       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
800                   ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
801      } else {
802       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
803                   ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
804     }
805     return;
806   case offset12:
807   case offset12scale2:
808   case offset12scale4:
809   case offset12scale8:
810   case offset12scale16:
811     if (ref.addend()) {
812       appendReloc(relocs, sectionOffset, ref.addend(), 0,
813                   ARM64_RELOC_ADDEND | rLength4);
814       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
815                   ARM64_RELOC_PAGEOFF12  | rExtern | rLength4);
816      } else {
817       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
818                   ARM64_RELOC_PAGEOFF12 | rExtern | rLength4);
819     }
820     return;
821   case gotPage21:
822     assert(ref.addend() == 0);
823     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
824                   ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
825     return;
826   case gotOffset12:
827     assert(ref.addend() == 0);
828     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
829                   ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4);
830     return;
831   case tlvPage21:
832     assert(ref.addend() == 0);
833     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
834                   ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
835     return;
836   case tlvOffset12:
837     assert(ref.addend() == 0);
838     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
839                   ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4);
840     return;
841   case pointer64:
842     if (ref.target()->name().empty())
843       appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
844                   ARM64_RELOC_UNSIGNED           | rLength8);
845     else
846       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
847                   ARM64_RELOC_UNSIGNED | rExtern | rLength8);
848     return;
849   case delta64:
850     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
851                 ARM64_RELOC_SUBTRACTOR | rExtern | rLength8);
852     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
853                 ARM64_RELOC_UNSIGNED  | rExtern | rLength8);
854     return;
855   case delta32:
856     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
857                 ARM64_RELOC_SUBTRACTOR | rExtern | rLength4 );
858     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
859                 ARM64_RELOC_UNSIGNED   | rExtern | rLength4 );
860     return;
861   case pointer64ToGOT:
862     assert(ref.addend() == 0);
863     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
864                   ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8);
865     return;
866   case delta32ToGOT:
867     assert(ref.addend() == 0);
868     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
869                   ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4);
870     return;
871   case addOffset12:
872     llvm_unreachable("lazy reference kind implies GOT pass was run");
873   case lazyPointer:
874   case lazyImmediateLocation:
875     llvm_unreachable("lazy reference kind implies Stubs pass was run");
876   case imageOffset:
877   case imageOffsetGot:
878     llvm_unreachable("deltas from mach_header can only be in final images");
879   case unwindCIEToPersonalityFunction:
880   case unwindFDEToFunction:
881   case unwindInfoToEhFrame:
882   case negDelta32:
883     // Do nothing.
884     return;
885   case invalid:
886     // Fall into llvm_unreachable().
887     break;
888   }
889   llvm_unreachable("unknown arm64 Reference Kind");
890 }
891
892 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm64() {
893   return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm64());
894 }
895
896 } // namespace mach_o
897 } // namespace lld