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