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