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