]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
Bring lld (release_39 branch, r279477) to contrib
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / lib / ReaderWriter / MachO / ArchHandler_x86_64.cpp
1 //===- lib/FileFormat/MachO/ArchHandler_x86_64.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
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_x86_64 : public ArchHandler {
32 public:
33   ArchHandler_x86_64() = default;
34   ~ArchHandler_x86_64() override = default;
35
36   const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
37
38   Reference::KindArch kindArch() override {
39     return Reference::KindArch::x86_64;
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::x86_64);
47     switch (ref.kindValue()) {
48     case ripRel32GotLoad:
49       canBypassGOT = true;
50       return true;
51     case ripRel32Got:
52       canBypassGOT = false;
53       return true;
54     case imageOffsetGot:
55       canBypassGOT = false;
56       return true;
57     default:
58       return false;
59     }
60   }
61
62   bool isTLVAccess(const Reference &ref) const override {
63     assert(ref.kindNamespace() == Reference::KindNamespace::mach_o);
64     assert(ref.kindArch() == Reference::KindArch::x86_64);
65     return ref.kindValue() == ripRel32Tlv;
66   }
67
68   void updateReferenceToTLV(const Reference *ref) override {
69     assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
70     assert(ref->kindArch() == Reference::KindArch::x86_64);
71     assert(ref->kindValue() == ripRel32Tlv);
72     const_cast<Reference*>(ref)->setKindValue(ripRel32);
73   }
74
75   /// Used by GOTPass to update GOT References
76   void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
77     assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
78     assert(ref->kindArch() == Reference::KindArch::x86_64);
79
80     switch (ref->kindValue()) {
81     case ripRel32Got:
82       assert(targetNowGOT && "target must be GOT");
83     case ripRel32GotLoad:
84       const_cast<Reference *>(ref)
85         ->setKindValue(targetNowGOT ? ripRel32 : ripRel32GotLoadNowLea);
86       break;
87     case imageOffsetGot:
88       const_cast<Reference *>(ref)->setKindValue(imageOffset);
89       break;
90     default:
91       llvm_unreachable("unknown GOT reference kind");
92     }
93   }
94
95   bool needsCompactUnwind() override {
96     return true;
97   }
98
99   Reference::KindValue imageOffsetKind() override {
100     return imageOffset;
101   }
102
103   Reference::KindValue imageOffsetKindIndirect() override {
104     return imageOffsetGot;
105   }
106
107   Reference::KindValue unwindRefToPersonalityFunctionKind() override {
108     return ripRel32Got;
109   }
110
111   Reference::KindValue unwindRefToCIEKind() override {
112     return negDelta32;
113   }
114
115   Reference::KindValue unwindRefToFunctionKind() override{
116     return unwindFDEToFunction;
117   }
118
119   Reference::KindValue unwindRefToEhFrameKind() override {
120     return unwindInfoToEhFrame;
121   }
122
123   Reference::KindValue pointerKind() override {
124     return pointer64;
125   }
126
127   uint32_t dwarfCompactUnwindType() override {
128     return 0x04000000U;
129   }
130
131   const StubInfo &stubInfo() override { return _sStubInfo; }
132
133   bool isNonCallBranch(const Reference &) override {
134     return false;
135   }
136
137   bool isCallSite(const Reference &) override;
138   bool isPointer(const Reference &) override;
139   bool isPairedReloc(const normalized::Relocation &) override;
140
141   llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
142                                const DefinedAtom *inAtom,
143                                uint32_t offsetInAtom,
144                                uint64_t fixupAddress, bool swap,
145                                FindAtomBySectionAndAddress atomFromAddress,
146                                FindAtomBySymbolIndex atomFromSymbolIndex,
147                                Reference::KindValue *kind,
148                                const lld::Atom **target,
149                                Reference::Addend *addend) override;
150   llvm::Error
151       getPairReferenceInfo(const normalized::Relocation &reloc1,
152                            const normalized::Relocation &reloc2,
153                            const DefinedAtom *inAtom,
154                            uint32_t offsetInAtom,
155                            uint64_t fixupAddress, bool swap, bool scatterable,
156                            FindAtomBySectionAndAddress atomFromAddress,
157                            FindAtomBySymbolIndex atomFromSymbolIndex,
158                            Reference::KindValue *kind,
159                            const lld::Atom **target,
160                            Reference::Addend *addend) override;
161
162   bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override {
163     return (atom->contentType() == DefinedAtom::typeCString);
164   }
165
166   void generateAtomContent(const DefinedAtom &atom, bool relocatable,
167                            FindAddressForAtom findAddress,
168                            FindAddressForAtom findSectionAddress,
169                            uint64_t imageBase,
170                     llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
171
172   void appendSectionRelocations(const DefinedAtom &atom,
173                                 uint64_t atomSectionOffset,
174                                 const Reference &ref,
175                                 FindSymbolIndexForAtom symbolIndexForAtom,
176                                 FindSectionIndexForAtom sectionIndexForAtom,
177                                 FindAddressForAtom addressForAtom,
178                                 normalized::Relocations &relocs) override;
179
180 private:
181   static const Registry::KindStrings _sKindStrings[];
182   static const StubInfo              _sStubInfo;
183
184   enum X86_64Kind: Reference::KindValue {
185     invalid,               /// for error condition
186
187     // Kinds found in mach-o .o files:
188     branch32,              /// ex: call _foo
189     ripRel32,              /// ex: movq _foo(%rip), %rax
190     ripRel32Minus1,        /// ex: movb $0x12, _foo(%rip)
191     ripRel32Minus2,        /// ex: movw $0x1234, _foo(%rip)
192     ripRel32Minus4,        /// ex: movl $0x12345678, _foo(%rip)
193     ripRel32Anon,          /// ex: movq L1(%rip), %rax
194     ripRel32Minus1Anon,    /// ex: movb $0x12, L1(%rip)
195     ripRel32Minus2Anon,    /// ex: movw $0x1234, L1(%rip)
196     ripRel32Minus4Anon,    /// ex: movw $0x12345678, L1(%rip)
197     ripRel32GotLoad,       /// ex: movq  _foo@GOTPCREL(%rip), %rax
198     ripRel32Got,           /// ex: pushq _foo@GOTPCREL(%rip)
199     ripRel32Tlv,           /// ex: movq  _foo@TLVP(%rip), %rdi
200     pointer64,             /// ex: .quad _foo
201     pointer64Anon,         /// ex: .quad L1
202     delta64,               /// ex: .quad _foo - .
203     delta32,               /// ex: .long _foo - .
204     delta64Anon,           /// ex: .quad L1 - .
205     delta32Anon,           /// ex: .long L1 - .
206     negDelta64,            /// ex: .quad . - _foo
207     negDelta32,            /// ex: .long . - _foo
208
209     // Kinds introduced by Passes:
210     ripRel32GotLoadNowLea, /// Target of GOT load is in linkage unit so
211                            ///  "movq  _foo@GOTPCREL(%rip), %rax" can be changed
212                            /// to "leaq _foo(%rip), %rax
213     lazyPointer,           /// Location contains a lazy pointer.
214     lazyImmediateLocation, /// Location contains immediate value used in stub.
215
216     imageOffset,           /// Location contains offset of atom in final image
217     imageOffsetGot,        /// Location contains offset of GOT entry for atom in
218                            /// final image (typically personality function).
219     unwindFDEToFunction,   /// Nearly delta64, but cannot be rematerialized in
220                            /// relocatable object (yay for implicit contracts!).
221     unwindInfoToEhFrame,   /// Fix low 24 bits of compact unwind encoding to
222                            /// refer to __eh_frame entry.
223     tlvInitSectionOffset   /// Location contains offset tlv init-value atom
224                            /// within the __thread_data section.
225   };
226
227   Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
228
229   void applyFixupFinal(const Reference &ref, uint8_t *location,
230                        uint64_t fixupAddress, uint64_t targetAddress,
231                        uint64_t inAtomAddress, uint64_t imageBaseAddress,
232                        FindAddressForAtom findSectionAddress);
233
234   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
235                              uint64_t fixupAddress,
236                              uint64_t targetAddress,
237                              uint64_t inAtomAddress);
238 };
239
240 const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = {
241   LLD_KIND_STRING_ENTRY(invalid), LLD_KIND_STRING_ENTRY(branch32),
242   LLD_KIND_STRING_ENTRY(ripRel32), LLD_KIND_STRING_ENTRY(ripRel32Minus1),
243   LLD_KIND_STRING_ENTRY(ripRel32Minus2), LLD_KIND_STRING_ENTRY(ripRel32Minus4),
244   LLD_KIND_STRING_ENTRY(ripRel32Anon),
245   LLD_KIND_STRING_ENTRY(ripRel32Minus1Anon),
246   LLD_KIND_STRING_ENTRY(ripRel32Minus2Anon),
247   LLD_KIND_STRING_ENTRY(ripRel32Minus4Anon),
248   LLD_KIND_STRING_ENTRY(ripRel32GotLoad),
249   LLD_KIND_STRING_ENTRY(ripRel32GotLoadNowLea),
250   LLD_KIND_STRING_ENTRY(ripRel32Got), LLD_KIND_STRING_ENTRY(ripRel32Tlv),
251   LLD_KIND_STRING_ENTRY(lazyPointer),
252   LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
253   LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(pointer64Anon),
254   LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(delta64),
255   LLD_KIND_STRING_ENTRY(delta32Anon), LLD_KIND_STRING_ENTRY(delta64Anon),
256   LLD_KIND_STRING_ENTRY(negDelta64),
257   LLD_KIND_STRING_ENTRY(negDelta32),
258   LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot),
259   LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
260   LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
261   LLD_KIND_STRING_ENTRY(tlvInitSectionOffset),
262   LLD_KIND_STRING_END
263 };
264
265 const ArchHandler::StubInfo ArchHandler_x86_64::_sStubInfo = {
266   "dyld_stub_binder",
267
268   // Lazy pointer references
269   { Reference::KindArch::x86_64, pointer64, 0, 0 },
270   { Reference::KindArch::x86_64, lazyPointer, 0, 0 },
271
272   // GOT pointer to dyld_stub_binder
273   { Reference::KindArch::x86_64, pointer64, 0, 0 },
274
275   // x86_64 code alignment 2^1
276   1,
277
278   // Stub size and code
279   6,
280   { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 },       // jmp *lazyPointer
281   { Reference::KindArch::x86_64, ripRel32, 2, 0 },
282   { false, 0, 0, 0 },
283
284   // Stub Helper size and code
285   10,
286   { 0x68, 0x00, 0x00, 0x00, 0x00,               // pushq $lazy-info-offset
287     0xE9, 0x00, 0x00, 0x00, 0x00 },             // jmp helperhelper
288   { Reference::KindArch::x86_64, lazyImmediateLocation, 1, 0 },
289   { Reference::KindArch::x86_64, branch32, 6, 0 },
290
291   // Stub helper image cache content type
292   DefinedAtom::typeNonLazyPointer,
293
294   // Stub Helper-Common size and code
295   16,
296   // Stub helper alignment
297   2,
298   { 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00,   // leaq cache(%rip),%r11
299     0x41, 0x53,                                 // push %r11
300     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,         // jmp *binder(%rip)
301     0x90 },                                     // nop
302   { Reference::KindArch::x86_64, ripRel32, 3, 0 },
303   { false, 0, 0, 0 },
304   { Reference::KindArch::x86_64, ripRel32, 11, 0 },
305   { false, 0, 0, 0 }
306
307 };
308
309 bool ArchHandler_x86_64::isCallSite(const Reference &ref) {
310   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
311     return false;
312   assert(ref.kindArch() == Reference::KindArch::x86_64);
313   return (ref.kindValue() == branch32);
314 }
315
316 bool ArchHandler_x86_64::isPointer(const Reference &ref) {
317   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
318     return false;
319   assert(ref.kindArch() == Reference::KindArch::x86_64);
320   Reference::KindValue kind = ref.kindValue();
321   return (kind == pointer64 || kind == pointer64Anon);
322 }
323
324 bool ArchHandler_x86_64::isPairedReloc(const Relocation &reloc) {
325   return (reloc.type == X86_64_RELOC_SUBTRACTOR);
326 }
327
328 Reference::KindValue
329 ArchHandler_x86_64::kindFromReloc(const Relocation &reloc) {
330   switch(relocPattern(reloc)) {
331   case X86_64_RELOC_BRANCH   | rPcRel | rExtern | rLength4:
332     return branch32;
333   case X86_64_RELOC_SIGNED   | rPcRel | rExtern | rLength4:
334     return ripRel32;
335   case X86_64_RELOC_SIGNED   | rPcRel |           rLength4:
336     return ripRel32Anon;
337   case X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4:
338     return ripRel32Minus1;
339   case X86_64_RELOC_SIGNED_1 | rPcRel |           rLength4:
340     return ripRel32Minus1Anon;
341   case X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4:
342     return ripRel32Minus2;
343   case X86_64_RELOC_SIGNED_2 | rPcRel |           rLength4:
344     return ripRel32Minus2Anon;
345   case X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4:
346     return ripRel32Minus4;
347   case X86_64_RELOC_SIGNED_4 | rPcRel |           rLength4:
348     return ripRel32Minus4Anon;
349   case X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4:
350     return ripRel32GotLoad;
351   case X86_64_RELOC_GOT      | rPcRel | rExtern | rLength4:
352     return ripRel32Got;
353   case X86_64_RELOC_TLV      | rPcRel | rExtern | rLength4:
354     return ripRel32Tlv;
355   case X86_64_RELOC_UNSIGNED          | rExtern | rLength8:
356     return pointer64;
357   case X86_64_RELOC_UNSIGNED                    | rLength8:
358     return pointer64Anon;
359   default:
360     return invalid;
361   }
362 }
363
364 llvm::Error
365 ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
366                                     const DefinedAtom *inAtom,
367                                     uint32_t offsetInAtom,
368                                     uint64_t fixupAddress, bool swap,
369                                     FindAtomBySectionAndAddress atomFromAddress,
370                                     FindAtomBySymbolIndex atomFromSymbolIndex,
371                                     Reference::KindValue *kind,
372                                     const lld::Atom **target,
373                                     Reference::Addend *addend) {
374   *kind = kindFromReloc(reloc);
375   if (*kind == invalid)
376     return llvm::make_error<GenericError>("unknown type");
377   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
378   uint64_t targetAddress;
379   switch (*kind) {
380   case branch32:
381   case ripRel32:
382     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
383       return ec;
384     *addend = *(const little32_t *)fixupContent;
385     return llvm::Error();
386   case ripRel32Minus1:
387     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
388       return ec;
389     *addend = (int32_t)*(const little32_t *)fixupContent + 1;
390     return llvm::Error();
391   case ripRel32Minus2:
392     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
393       return ec;
394     *addend = (int32_t)*(const little32_t *)fixupContent + 2;
395     return llvm::Error();
396   case ripRel32Minus4:
397     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
398       return ec;
399     *addend = (int32_t)*(const little32_t *)fixupContent + 4;
400     return llvm::Error();
401   case ripRel32Anon:
402     targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent;
403     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
404   case ripRel32Minus1Anon:
405     targetAddress = fixupAddress + 5 + *(const little32_t *)fixupContent;
406     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
407   case ripRel32Minus2Anon:
408     targetAddress = fixupAddress + 6 + *(const little32_t *)fixupContent;
409     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
410   case ripRel32Minus4Anon:
411     targetAddress = fixupAddress + 8 + *(const little32_t *)fixupContent;
412     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
413   case ripRel32GotLoad:
414   case ripRel32Got:
415   case ripRel32Tlv:
416     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
417       return ec;
418     *addend = *(const little32_t *)fixupContent;
419     return llvm::Error();
420   case tlvInitSectionOffset:
421   case pointer64:
422     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
423       return ec;
424     // If this is the 3rd pointer of a tlv-thunk (i.e. the pointer to the TLV's
425     // initial value) we need to handle it specially.
426     if (inAtom->contentType() == DefinedAtom::typeThunkTLV &&
427         offsetInAtom == 16) {
428       *kind = tlvInitSectionOffset;
429       assert(*addend == 0 && "TLV-init has non-zero addend?");
430     } else
431       *addend = *(const little64_t *)fixupContent;
432     return llvm::Error();
433   case pointer64Anon:
434     targetAddress = *(const little64_t *)fixupContent;
435     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
436   default:
437     llvm_unreachable("bad reloc kind");
438   }
439 }
440
441 llvm::Error
442 ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
443                                    const normalized::Relocation &reloc2,
444                                    const DefinedAtom *inAtom,
445                                    uint32_t offsetInAtom,
446                                    uint64_t fixupAddress, bool swap,
447                                    bool scatterable,
448                                    FindAtomBySectionAndAddress atomFromAddress,
449                                    FindAtomBySymbolIndex atomFromSymbolIndex,
450                                    Reference::KindValue *kind,
451                                    const lld::Atom **target,
452                                    Reference::Addend *addend) {
453   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
454   uint64_t targetAddress;
455   const lld::Atom *fromTarget;
456   if (auto ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
457     return ec;
458
459   switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
460   case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
461         X86_64_RELOC_UNSIGNED    | rExtern | rLength8): {
462     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
463       return ec;
464     uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent;
465     if (inAtom == fromTarget) {
466       *kind = delta64;
467       *addend = encodedAddend + offsetInAtom;
468     } else if (inAtom == *target) {
469       *kind = negDelta64;
470       *addend = encodedAddend - offsetInAtom;
471       *target = fromTarget;
472     } else
473       return llvm::make_error<GenericError>("Invalid pointer diff");
474     return llvm::Error();
475   }
476   case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
477         X86_64_RELOC_UNSIGNED    | rExtern | rLength4): {
478     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
479       return ec;
480     uint32_t encodedAddend = (int32_t)*(const little32_t *)fixupContent;
481     if (inAtom == fromTarget) {
482       *kind = delta32;
483       *addend = encodedAddend + offsetInAtom;
484     } else if (inAtom == *target) {
485       *kind = negDelta32;
486       *addend = encodedAddend - offsetInAtom;
487       *target = fromTarget;
488     } else
489       return llvm::make_error<GenericError>("Invalid pointer diff");
490     return llvm::Error();
491   }
492   case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
493         X86_64_RELOC_UNSIGNED              | rLength8):
494     if (fromTarget != inAtom)
495       return llvm::make_error<GenericError>("pointer diff not in base atom");
496     *kind = delta64Anon;
497     targetAddress = offsetInAtom + (int64_t)*(const little64_t *)fixupContent;
498     return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
499   case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
500         X86_64_RELOC_UNSIGNED              | rLength4):
501     if (fromTarget != inAtom)
502       return llvm::make_error<GenericError>("pointer diff not in base atom");
503     *kind = delta32Anon;
504     targetAddress = offsetInAtom + (int32_t)*(const little32_t *)fixupContent;
505     return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
506   default:
507     return llvm::make_error<GenericError>("unknown pair");
508   }
509 }
510
511 void ArchHandler_x86_64::generateAtomContent(
512     const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
513     FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
514     llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
515   // Copy raw bytes.
516   std::copy(atom.rawContent().begin(), atom.rawContent().end(),
517             atomContentBuffer.begin());
518   // Apply fix-ups.
519   for (const Reference *ref : atom) {
520     uint32_t offset = ref->offsetInAtom();
521     const Atom *target = ref->target();
522     uint64_t targetAddress = 0;
523     if (isa<DefinedAtom>(target))
524       targetAddress = findAddress(*target);
525     uint64_t atomAddress = findAddress(atom);
526     uint64_t fixupAddress = atomAddress + offset;
527     if (relocatable) {
528       applyFixupRelocatable(*ref, &atomContentBuffer[offset],
529                                         fixupAddress, targetAddress,
530                                         atomAddress);
531     } else {
532       applyFixupFinal(*ref, &atomContentBuffer[offset],
533                       fixupAddress, targetAddress,
534                       atomAddress, imageBaseAddress, findSectionAddress);
535     }
536   }
537 }
538
539 void ArchHandler_x86_64::applyFixupFinal(
540     const Reference &ref, uint8_t *loc, uint64_t fixupAddress,
541     uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress,
542     FindAddressForAtom findSectionAddress) {
543   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
544     return;
545   assert(ref.kindArch() == Reference::KindArch::x86_64);
546   ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
547   ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
548   switch (static_cast<X86_64Kind>(ref.kindValue())) {
549   case branch32:
550   case ripRel32:
551   case ripRel32Anon:
552   case ripRel32Got:
553   case ripRel32GotLoad:
554   case ripRel32Tlv:
555     *loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
556     return;
557   case pointer64:
558   case pointer64Anon:
559     *loc64 = targetAddress + ref.addend();
560     return;
561   case tlvInitSectionOffset:
562     *loc64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
563     return;
564   case ripRel32Minus1:
565   case ripRel32Minus1Anon:
566     *loc32 = targetAddress - (fixupAddress + 5) + ref.addend();
567     return;
568   case ripRel32Minus2:
569   case ripRel32Minus2Anon:
570     *loc32 = targetAddress - (fixupAddress + 6) + ref.addend();
571     return;
572   case ripRel32Minus4:
573   case ripRel32Minus4Anon:
574     *loc32 = targetAddress - (fixupAddress + 8) + ref.addend();
575     return;
576   case delta32:
577   case delta32Anon:
578     *loc32 = targetAddress - fixupAddress + ref.addend();
579     return;
580   case delta64:
581   case delta64Anon:
582   case unwindFDEToFunction:
583     *loc64 = targetAddress - fixupAddress + ref.addend();
584     return;
585   case ripRel32GotLoadNowLea:
586     // Change MOVQ to LEA
587     assert(loc[-2] == 0x8B);
588     loc[-2] = 0x8D;
589     *loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
590     return;
591   case negDelta64:
592     *loc64 = fixupAddress - targetAddress + ref.addend();
593     return;
594   case negDelta32:
595     *loc32 = fixupAddress - targetAddress + ref.addend();
596     return;
597   case lazyPointer:
598     // Do nothing
599     return;
600   case lazyImmediateLocation:
601     *loc32 = ref.addend();
602     return;
603   case imageOffset:
604   case imageOffsetGot:
605     *loc32 = (targetAddress - imageBaseAddress) + ref.addend();
606     return;
607   case unwindInfoToEhFrame: {
608     uint64_t val = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
609     assert(val < 0xffffffU && "offset in __eh_frame too large");
610     *loc32 = (*loc32 & 0xff000000U) | val;
611     return;
612   }
613   case invalid:
614     // Fall into llvm_unreachable().
615     break;
616   }
617   llvm_unreachable("invalid x86_64 Reference Kind");
618 }
619
620 void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
621                                                uint8_t *loc,
622                                                uint64_t fixupAddress,
623                                                uint64_t targetAddress,
624                                                uint64_t inAtomAddress)  {
625   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
626     return;
627   assert(ref.kindArch() == Reference::KindArch::x86_64);
628   ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
629   ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
630   switch (static_cast<X86_64Kind>(ref.kindValue())) {
631   case branch32:
632   case ripRel32:
633   case ripRel32Got:
634   case ripRel32GotLoad:
635   case ripRel32Tlv:
636     *loc32 = ref.addend();
637     return;
638   case ripRel32Anon:
639     *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
640     return;
641   case tlvInitSectionOffset:
642   case pointer64:
643     *loc64 = ref.addend();
644     return;
645   case pointer64Anon:
646     *loc64 = targetAddress + ref.addend();
647     return;
648   case ripRel32Minus1:
649     *loc32 = ref.addend() - 1;
650     return;
651   case ripRel32Minus1Anon:
652     *loc32 = (targetAddress - (fixupAddress + 5)) + ref.addend();
653     return;
654   case ripRel32Minus2:
655     *loc32 = ref.addend() - 2;
656     return;
657   case ripRel32Minus2Anon:
658     *loc32 = (targetAddress - (fixupAddress + 6)) + ref.addend();
659     return;
660   case ripRel32Minus4:
661     *loc32 = ref.addend() - 4;
662     return;
663   case ripRel32Minus4Anon:
664     *loc32 = (targetAddress - (fixupAddress + 8)) + ref.addend();
665     return;
666   case delta32:
667     *loc32 = ref.addend() + inAtomAddress - fixupAddress;
668     return;
669   case delta32Anon:
670     // The value we write here should be the the delta to the target
671     // after taking in to account the difference from the fixup back to the
672     // last defined label
673     // ie, if we have:
674     // _base: ...
675     // Lfixup: .quad Ltarget - .
676     // ...
677     // Ltarget:
678     //
679     // Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
680     *loc32 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
681     return;
682   case delta64:
683     *loc64 = ref.addend() + inAtomAddress - fixupAddress;
684     return;
685   case delta64Anon:
686     // The value we write here should be the the delta to the target
687     // after taking in to account the difference from the fixup back to the
688     // last defined label
689     // ie, if we have:
690     // _base: ...
691     // Lfixup: .quad Ltarget - .
692     // ...
693     // Ltarget:
694     //
695     // Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
696     *loc64 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
697     return;
698   case negDelta64:
699     *loc64 = ref.addend() + fixupAddress - inAtomAddress;
700     return;
701   case negDelta32:
702     *loc32 = ref.addend() + fixupAddress - inAtomAddress;
703     return;
704   case ripRel32GotLoadNowLea:
705     llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
706     return;
707   case lazyPointer:
708   case lazyImmediateLocation:
709     llvm_unreachable("lazy reference kind implies Stubs pass was run");
710     return;
711   case imageOffset:
712   case imageOffsetGot:
713   case unwindInfoToEhFrame:
714     llvm_unreachable("fixup implies __unwind_info");
715     return;
716   case unwindFDEToFunction:
717     // Do nothing for now
718     return;
719   case invalid:
720     // Fall into llvm_unreachable().
721     break;
722   }
723   llvm_unreachable("unknown x86_64 Reference Kind");
724 }
725
726 void ArchHandler_x86_64::appendSectionRelocations(
727                                    const DefinedAtom &atom,
728                                    uint64_t atomSectionOffset,
729                                    const Reference &ref,
730                                    FindSymbolIndexForAtom symbolIndexForAtom,
731                                    FindSectionIndexForAtom sectionIndexForAtom,
732                                    FindAddressForAtom addressForAtom,
733                                    normalized::Relocations &relocs) {
734   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
735     return;
736   assert(ref.kindArch() == Reference::KindArch::x86_64);
737   uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
738   switch (static_cast<X86_64Kind>(ref.kindValue())) {
739   case branch32:
740     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
741                 X86_64_RELOC_BRANCH | rPcRel | rExtern | rLength4);
742     return;
743   case ripRel32:
744     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
745                 X86_64_RELOC_SIGNED | rPcRel | rExtern | rLength4 );
746     return;
747   case ripRel32Anon:
748     appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
749                 X86_64_RELOC_SIGNED | rPcRel           | rLength4 );
750     return;
751   case ripRel32Got:
752     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
753                 X86_64_RELOC_GOT | rPcRel | rExtern | rLength4 );
754     return;
755   case ripRel32GotLoad:
756     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
757                 X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4 );
758     return;
759   case ripRel32Tlv:
760     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
761                 X86_64_RELOC_TLV | rPcRel | rExtern | rLength4 );
762     return;
763   case tlvInitSectionOffset:
764   case pointer64:
765     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
766                 X86_64_RELOC_UNSIGNED  | rExtern | rLength8);
767     return;
768   case pointer64Anon:
769     appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
770                 X86_64_RELOC_UNSIGNED | rLength8);
771     return;
772   case ripRel32Minus1:
773     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
774                 X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4 );
775     return;
776   case ripRel32Minus1Anon:
777     appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
778                 X86_64_RELOC_SIGNED_1 | rPcRel           | rLength4 );
779     return;
780   case ripRel32Minus2:
781     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
782                 X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4 );
783     return;
784   case ripRel32Minus2Anon:
785     appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
786                 X86_64_RELOC_SIGNED_2 | rPcRel           | rLength4 );
787     return;
788   case ripRel32Minus4:
789     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
790                 X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4 );
791     return;
792   case ripRel32Minus4Anon:
793     appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
794                 X86_64_RELOC_SIGNED_4 | rPcRel           | rLength4 );
795     return;
796   case delta32:
797     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
798                 X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
799     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
800                 X86_64_RELOC_UNSIGNED   | rExtern | rLength4 );
801     return;
802   case delta32Anon:
803     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
804                 X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
805     appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
806                 X86_64_RELOC_UNSIGNED             | rLength4 );
807     return;
808   case delta64:
809     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
810                 X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
811     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
812                 X86_64_RELOC_UNSIGNED   | rExtern | rLength8 );
813     return;
814   case delta64Anon:
815     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
816                 X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
817     appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
818                 X86_64_RELOC_UNSIGNED             | rLength8 );
819     return;
820   case unwindFDEToFunction:
821   case unwindInfoToEhFrame:
822     return;
823   case negDelta32:
824     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
825                 X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
826     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
827                 X86_64_RELOC_UNSIGNED   | rExtern | rLength4 );
828     return;
829   case negDelta64:
830     appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
831                 X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
832     appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
833                 X86_64_RELOC_UNSIGNED   | rExtern | rLength8 );
834     return;
835   case ripRel32GotLoadNowLea:
836     llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
837     return;
838   case lazyPointer:
839   case lazyImmediateLocation:
840     llvm_unreachable("lazy reference kind implies Stubs pass was run");
841     return;
842   case imageOffset:
843   case imageOffsetGot:
844     llvm_unreachable("__unwind_info references should have been resolved");
845     return;
846   case invalid:
847     // Fall into llvm_unreachable().
848     break;
849   }
850   llvm_unreachable("unknown x86_64 Reference Kind");
851 }
852
853 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86_64() {
854   return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86_64());
855 }
856
857 } // namespace mach_o
858 } // namespace lld