1 //===- lib/FileFormat/MachO/ArchHandler_x86.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::ulittle16_t;
26 using llvm::support::ulittle32_t;
27 
28 using llvm::support::little16_t;
29 using llvm::support::little32_t;
30 
31 class ArchHandler_x86 : public ArchHandler {
32 public:
33   ArchHandler_x86() = default;
34   ~ArchHandler_x86() override = default;
35 
36   const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
37 
38   Reference::KindArch kindArch() override { return Reference::KindArch::x86; }
39 
40   const StubInfo &stubInfo() override { return _sStubInfo; }
41   bool isCallSite(const Reference &) override;
42   bool isNonCallBranch(const Reference &) override {
43     return false;
44   }
45 
46   bool isPointer(const Reference &) override;
47   bool isPairedReloc(const normalized::Relocation &) override;
48 
49   bool needsCompactUnwind() override {
50     return false;
51   }
52 
53   Reference::KindValue imageOffsetKind() override {
54     return invalid;
55   }
56 
57   Reference::KindValue imageOffsetKindIndirect() override {
58     return invalid;
59   }
60 
61   Reference::KindValue unwindRefToPersonalityFunctionKind() override {
62     return invalid;
63   }
64 
65   Reference::KindValue unwindRefToCIEKind() override {
66     return negDelta32;
67   }
68 
69   Reference::KindValue unwindRefToFunctionKind() override{
70     return delta32;
71   }
72 
73   Reference::KindValue unwindRefToEhFrameKind() override {
74     return invalid;
75   }
76 
77   Reference::KindValue pointerKind() override {
78     return invalid;
79   }
80 
81   uint32_t dwarfCompactUnwindType() override {
82     return 0x04000000U;
83   }
84 
85   llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
86                                const DefinedAtom *inAtom,
87                                uint32_t offsetInAtom,
88                                uint64_t fixupAddress, bool swap,
89                                FindAtomBySectionAndAddress atomFromAddress,
90                                FindAtomBySymbolIndex atomFromSymbolIndex,
91                                Reference::KindValue *kind,
92                                const lld::Atom **target,
93                                Reference::Addend *addend) override;
94   llvm::Error
95       getPairReferenceInfo(const normalized::Relocation &reloc1,
96                            const normalized::Relocation &reloc2,
97                            const DefinedAtom *inAtom,
98                            uint32_t offsetInAtom,
99                            uint64_t fixupAddress, bool swap, bool scatterable,
100                            FindAtomBySectionAndAddress atomFromAddress,
101                            FindAtomBySymbolIndex atomFromSymbolIndex,
102                            Reference::KindValue *kind,
103                            const lld::Atom **target,
104                            Reference::Addend *addend) override;
105 
106   void generateAtomContent(const DefinedAtom &atom, bool relocatable,
107                            FindAddressForAtom findAddress,
108                            FindAddressForAtom findSectionAddress,
109                            uint64_t imageBaseAddress,
110                     llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
111 
112   void appendSectionRelocations(const DefinedAtom &atom,
113                                 uint64_t atomSectionOffset,
114                                 const Reference &ref,
115                                 FindSymbolIndexForAtom symbolIndexForAtom,
116                                 FindSectionIndexForAtom sectionIndexForAtom,
117                                 FindAddressForAtom addressForAtom,
118                                 normalized::Relocations &relocs) override;
119 
120   bool isDataInCodeTransition(Reference::KindValue refKind) override {
121     switch (refKind) {
122     case modeCode:
123     case modeData:
124       return true;
125     default:
126       return false;
127       break;
128     }
129   }
130 
131   Reference::KindValue dataInCodeTransitionStart(
132                                         const MachODefinedAtom &atom) override {
133     return modeData;
134   }
135 
136   Reference::KindValue dataInCodeTransitionEnd(
137                                         const MachODefinedAtom &atom) override {
138     return modeCode;
139   }
140 
141 private:
142   static const Registry::KindStrings _sKindStrings[];
143   static const StubInfo              _sStubInfo;
144 
145   enum X86Kind : Reference::KindValue {
146     invalid,               /// for error condition
147 
148     modeCode,              /// Content starting at this offset is code.
149     modeData,              /// Content starting at this offset is data.
150 
151     // Kinds found in mach-o .o files:
152     branch32,              /// ex: call _foo
153     branch16,              /// ex: callw _foo
154     abs32,                 /// ex: movl _foo, %eax
155     funcRel32,             /// ex: movl _foo-L1(%eax), %eax
156     pointer32,             /// ex: .long _foo
157     delta32,               /// ex: .long _foo - .
158     negDelta32,            /// ex: .long . - _foo
159 
160     // Kinds introduced by Passes:
161     lazyPointer,           /// Location contains a lazy pointer.
162     lazyImmediateLocation, /// Location contains immediate value used in stub.
163   };
164 
165   static bool useExternalRelocationTo(const Atom &target);
166 
167   void applyFixupFinal(const Reference &ref, uint8_t *location,
168                        uint64_t fixupAddress, uint64_t targetAddress,
169                        uint64_t inAtomAddress);
170 
171   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
172                              uint64_t fixupAddress,
173                              uint64_t targetAddress,
174                              uint64_t inAtomAddress);
175 };
176 
177 //===----------------------------------------------------------------------===//
178 //  ArchHandler_x86
179 //===----------------------------------------------------------------------===//
180 
181 const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = {
182   LLD_KIND_STRING_ENTRY(invalid),
183   LLD_KIND_STRING_ENTRY(modeCode),
184   LLD_KIND_STRING_ENTRY(modeData),
185   LLD_KIND_STRING_ENTRY(branch32),
186   LLD_KIND_STRING_ENTRY(branch16),
187   LLD_KIND_STRING_ENTRY(abs32),
188   LLD_KIND_STRING_ENTRY(funcRel32),
189   LLD_KIND_STRING_ENTRY(pointer32),
190   LLD_KIND_STRING_ENTRY(delta32),
191   LLD_KIND_STRING_ENTRY(negDelta32),
192   LLD_KIND_STRING_ENTRY(lazyPointer),
193   LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
194   LLD_KIND_STRING_END
195 };
196 
197 const ArchHandler::StubInfo ArchHandler_x86::_sStubInfo = {
198   "dyld_stub_binder",
199 
200   // Lazy pointer references
201   { Reference::KindArch::x86, pointer32, 0, 0 },
202   { Reference::KindArch::x86, lazyPointer, 0, 0 },
203 
204   // GOT pointer to dyld_stub_binder
205   { Reference::KindArch::x86, pointer32, 0, 0 },
206 
207   // x86 code alignment
208   1,
209 
210   // Stub size and code
211   6,
212   { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 },       // jmp *lazyPointer
213   { Reference::KindArch::x86, abs32, 2, 0 },
214   { false, 0, 0, 0 },
215 
216   // Stub Helper size and code
217   10,
218   { 0x68, 0x00, 0x00, 0x00, 0x00,               // pushl $lazy-info-offset
219     0xE9, 0x00, 0x00, 0x00, 0x00 },             // jmp helperhelper
220   { Reference::KindArch::x86, lazyImmediateLocation, 1, 0 },
221   { Reference::KindArch::x86, branch32, 6, 0 },
222 
223   // Stub helper image cache content type
224   DefinedAtom::typeNonLazyPointer,
225 
226   // Stub Helper-Common size and code
227   12,
228   // Stub helper alignment
229   2,
230   { 0x68, 0x00, 0x00, 0x00, 0x00,               // pushl $dyld_ImageLoaderCache
231     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,         // jmp *_fast_lazy_bind
232     0x90 },                                     // nop
233   { Reference::KindArch::x86, abs32, 1, 0 },
234   { false, 0, 0, 0 },
235   { Reference::KindArch::x86, abs32, 7, 0 },
236   { false, 0, 0, 0 }
237 };
238 
239 bool ArchHandler_x86::isCallSite(const Reference &ref) {
240   return (ref.kindValue() == branch32);
241 }
242 
243 bool ArchHandler_x86::isPointer(const Reference &ref) {
244   return (ref.kindValue() == pointer32);
245 }
246 
247 bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) {
248   if (!reloc.scattered)
249     return false;
250   return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) ||
251          (reloc.type == GENERIC_RELOC_SECTDIFF);
252 }
253 
254 llvm::Error
255 ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
256                                   const DefinedAtom *inAtom,
257                                   uint32_t offsetInAtom,
258                                   uint64_t fixupAddress, bool swap,
259                                   FindAtomBySectionAndAddress atomFromAddress,
260                                   FindAtomBySymbolIndex atomFromSymbolIndex,
261                                   Reference::KindValue *kind,
262                                   const lld::Atom **target,
263                                   Reference::Addend *addend) {
264   DefinedAtom::ContentPermissions perms;
265   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
266   uint64_t targetAddress;
267   switch (relocPattern(reloc)) {
268   case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
269     // ex: call _foo (and _foo undefined)
270     *kind = branch32;
271     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
272       return ec;
273     *addend = fixupAddress + 4 + (int32_t)*(const little32_t *)fixupContent;
274     break;
275   case GENERIC_RELOC_VANILLA | rPcRel | rLength4:
276     // ex: call _foo (and _foo defined)
277     *kind = branch32;
278     targetAddress =
279         fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
280     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
281     break;
282   case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
283     // ex: call _foo+n (and _foo defined)
284     *kind = branch32;
285     targetAddress =
286         fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
287     if (auto ec = atomFromAddress(0, reloc.value, target, addend))
288       return ec;
289     *addend = targetAddress - reloc.value;
290     break;
291   case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
292     // ex: callw _foo (and _foo undefined)
293     *kind = branch16;
294     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
295       return ec;
296     *addend = fixupAddress + 2 + (int16_t)*(const little16_t *)fixupContent;
297     break;
298   case GENERIC_RELOC_VANILLA | rPcRel | rLength2:
299     // ex: callw _foo (and _foo defined)
300     *kind = branch16;
301     targetAddress =
302         fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
303     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
304     break;
305   case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
306     // ex: callw _foo+n (and _foo defined)
307     *kind = branch16;
308     targetAddress =
309         fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
310     if (auto ec = atomFromAddress(0, reloc.value, target, addend))
311       return ec;
312     *addend = targetAddress - reloc.value;
313     break;
314   case GENERIC_RELOC_VANILLA | rExtern | rLength4:
315     // ex: movl	_foo, %eax   (and _foo undefined)
316     // ex: .long _foo        (and _foo undefined)
317     perms = inAtom->permissions();
318     *kind =
319         ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
320                                                                  : pointer32;
321     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
322       return ec;
323     *addend = *(const ulittle32_t *)fixupContent;
324     break;
325   case GENERIC_RELOC_VANILLA | rLength4:
326     // ex: movl	_foo, %eax   (and _foo defined)
327     // ex: .long _foo        (and _foo defined)
328     perms = inAtom->permissions();
329     *kind =
330         ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
331                                                                  : pointer32;
332     targetAddress = *(const ulittle32_t *)fixupContent;
333     return atomFromAddress(reloc.symbol, targetAddress, target, addend);
334     break;
335   case GENERIC_RELOC_VANILLA | rScattered | rLength4:
336     // ex: .long _foo+n      (and _foo defined)
337     perms = inAtom->permissions();
338     *kind =
339         ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
340                                                                  : pointer32;
341     if (auto ec = atomFromAddress(0, reloc.value, target, addend))
342       return ec;
343     *addend = *(const ulittle32_t *)fixupContent - reloc.value;
344     break;
345   default:
346     return llvm::make_error<GenericError>("unsupported i386 relocation type");
347   }
348   return llvm::Error();
349 }
350 
351 llvm::Error
352 ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
353                                       const normalized::Relocation &reloc2,
354                                       const DefinedAtom *inAtom,
355                                       uint32_t offsetInAtom,
356                                       uint64_t fixupAddress, bool swap,
357                                       bool scatterable,
358                                       FindAtomBySectionAndAddress atomFromAddr,
359                                       FindAtomBySymbolIndex atomFromSymbolIndex,
360                                       Reference::KindValue *kind,
361                                       const lld::Atom **target,
362                                       Reference::Addend *addend) {
363   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
364   DefinedAtom::ContentPermissions perms = inAtom->permissions();
365   uint32_t fromAddress;
366   uint32_t toAddress;
367   uint32_t value;
368   const lld::Atom *fromTarget;
369   Reference::Addend offsetInTo;
370   Reference::Addend offsetInFrom;
371   switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
372   case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
373          GENERIC_RELOC_PAIR | rScattered | rLength4):
374   case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
375          GENERIC_RELOC_PAIR | rScattered | rLength4):
376     toAddress = reloc1.value;
377     fromAddress = reloc2.value;
378     value = *(const little32_t *)fixupContent;
379     if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
380       return ec;
381     if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
382       return ec;
383     if (fromTarget != inAtom) {
384       if (*target != inAtom)
385         return llvm::make_error<GenericError>(
386             "SECTDIFF relocation where neither target is in atom");
387       *kind = negDelta32;
388       *addend = toAddress - value - fromAddress;
389       *target = fromTarget;
390     } else {
391       if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) {
392         // SECTDIFF relocations are used in i386 codegen where the function
393         // prolog does a CALL to the next instruction which POPs the return
394         // address into EBX which becomes the pic-base register.  The POP
395         // instruction is label the used for the subtrahend in expressions.
396         // The funcRel32 kind represents the 32-bit delta to some symbol from
397         // the start of the function (atom) containing the funcRel32.
398         *kind = funcRel32;
399         uint32_t ta = fromAddress + value - toAddress;
400         *addend = ta - offsetInFrom;
401       } else {
402         *kind = delta32;
403         *addend = fromAddress + value - toAddress;
404       }
405     }
406     return llvm::Error();
407     break;
408   default:
409     return llvm::make_error<GenericError>("unsupported i386 relocation type");
410   }
411 }
412 
413 void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
414                                           bool relocatable,
415                                           FindAddressForAtom findAddress,
416                                           FindAddressForAtom findSectionAddress,
417                                           uint64_t imageBaseAddress,
418                             llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
419   // Copy raw bytes.
420   std::copy(atom.rawContent().begin(), atom.rawContent().end(),
421             atomContentBuffer.begin());
422   // Apply fix-ups.
423   for (const Reference *ref : atom) {
424     uint32_t offset = ref->offsetInAtom();
425     const Atom *target = ref->target();
426     uint64_t targetAddress = 0;
427     if (isa<DefinedAtom>(target))
428       targetAddress = findAddress(*target);
429     uint64_t atomAddress = findAddress(atom);
430     uint64_t fixupAddress = atomAddress + offset;
431     if (relocatable) {
432       applyFixupRelocatable(*ref, &atomContentBuffer[offset],
433                                         fixupAddress, targetAddress,
434                                         atomAddress);
435     } else {
436       applyFixupFinal(*ref, &atomContentBuffer[offset],
437                                   fixupAddress, targetAddress,
438                                   atomAddress);
439     }
440   }
441 }
442 
443 void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *loc,
444                                       uint64_t fixupAddress,
445                                       uint64_t targetAddress,
446                                       uint64_t inAtomAddress) {
447   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
448     return;
449   assert(ref.kindArch() == Reference::KindArch::x86);
450   ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
451   switch (static_cast<X86Kind>(ref.kindValue())) {
452   case branch32:
453     *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
454     break;
455   case branch16:
456     *loc32 = (targetAddress - (fixupAddress + 2)) + ref.addend();
457     break;
458   case pointer32:
459   case abs32:
460     *loc32 = targetAddress + ref.addend();
461     break;
462   case funcRel32:
463     *loc32 = targetAddress - inAtomAddress + ref.addend();
464     break;
465   case delta32:
466     *loc32 = targetAddress - fixupAddress + ref.addend();
467     break;
468   case negDelta32:
469     *loc32 = fixupAddress - targetAddress + ref.addend();
470     break;
471   case modeCode:
472   case modeData:
473   case lazyPointer:
474     // do nothing
475     break;
476   case lazyImmediateLocation:
477     *loc32 = ref.addend();
478     break;
479   case invalid:
480     llvm_unreachable("invalid x86 Reference Kind");
481     break;
482   }
483 }
484 
485 void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
486                                                uint8_t *loc,
487                                                uint64_t fixupAddress,
488                                                uint64_t targetAddress,
489                                                uint64_t inAtomAddress) {
490   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
491     return;
492   assert(ref.kindArch() == Reference::KindArch::x86);
493   bool useExternalReloc = useExternalRelocationTo(*ref.target());
494   ulittle16_t *loc16 = reinterpret_cast<ulittle16_t *>(loc);
495   ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
496   switch (static_cast<X86Kind>(ref.kindValue())) {
497   case branch32:
498     if (useExternalReloc)
499       *loc32 = ref.addend() - (fixupAddress + 4);
500     else
501       *loc32  =(targetAddress - (fixupAddress+4)) + ref.addend();
502     break;
503   case branch16:
504     if (useExternalReloc)
505       *loc16 = ref.addend() - (fixupAddress + 2);
506     else
507       *loc16 = (targetAddress - (fixupAddress+2)) + ref.addend();
508     break;
509   case pointer32:
510   case abs32:
511     *loc32 = targetAddress + ref.addend();
512     break;
513   case funcRel32:
514     *loc32 = targetAddress - inAtomAddress + ref.addend(); // FIXME
515     break;
516   case delta32:
517     *loc32 = targetAddress - fixupAddress + ref.addend();
518     break;
519   case negDelta32:
520     *loc32 = fixupAddress - targetAddress + ref.addend();
521     break;
522   case modeCode:
523   case modeData:
524   case lazyPointer:
525   case lazyImmediateLocation:
526     // do nothing
527     break;
528   case invalid:
529     llvm_unreachable("invalid x86 Reference Kind");
530     break;
531   }
532 }
533 
534 bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
535   // Undefined symbols are referenced via external relocations.
536   if (isa<UndefinedAtom>(&target))
537     return true;
538   if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
539      switch (defAtom->merge()) {
540      case DefinedAtom::mergeAsTentative:
541        // Tentative definitions are referenced via external relocations.
542        return true;
543      case DefinedAtom::mergeAsWeak:
544      case DefinedAtom::mergeAsWeakAndAddressUsed:
545        // Global weak-defs are referenced via external relocations.
546        return (defAtom->scope() == DefinedAtom::scopeGlobal);
547      default:
548        break;
549     }
550   }
551   // Everything else is reference via an internal relocation.
552   return false;
553 }
554 
555 void ArchHandler_x86::appendSectionRelocations(
556                                    const DefinedAtom &atom,
557                                    uint64_t atomSectionOffset,
558                                    const Reference &ref,
559                                    FindSymbolIndexForAtom symbolIndexForAtom,
560                                    FindSectionIndexForAtom sectionIndexForAtom,
561                                    FindAddressForAtom addressForAtom,
562                                    normalized::Relocations &relocs) {
563   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
564     return;
565   assert(ref.kindArch() == Reference::KindArch::x86);
566   uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
567   bool useExternalReloc = useExternalRelocationTo(*ref.target());
568   switch (static_cast<X86Kind>(ref.kindValue())) {
569   case modeCode:
570   case modeData:
571     break;
572   case branch32:
573     if (useExternalReloc) {
574       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
575                   GENERIC_RELOC_VANILLA | rExtern    | rPcRel | rLength4);
576     } else {
577       if (ref.addend() != 0)
578         appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
579                   GENERIC_RELOC_VANILLA | rScattered | rPcRel |  rLength4);
580       else
581         appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
582                   GENERIC_RELOC_VANILLA |              rPcRel | rLength4);
583     }
584     break;
585   case branch16:
586     if (useExternalReloc) {
587       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
588                   GENERIC_RELOC_VANILLA | rExtern    | rPcRel | rLength2);
589     } else {
590       if (ref.addend() != 0)
591         appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
592                   GENERIC_RELOC_VANILLA | rScattered | rPcRel |  rLength2);
593       else
594         appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
595                   GENERIC_RELOC_VANILLA |              rPcRel | rLength2);
596     }
597     break;
598   case pointer32:
599   case abs32:
600     if (useExternalReloc)
601       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
602                 GENERIC_RELOC_VANILLA |    rExtern     |  rLength4);
603     else {
604       if (ref.addend() != 0)
605         appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
606                 GENERIC_RELOC_VANILLA |    rScattered  |  rLength4);
607       else
608         appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
609                 GENERIC_RELOC_VANILLA |                   rLength4);
610     }
611     break;
612   case funcRel32:
613     appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
614               GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
615     appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
616               GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
617     break;
618   case delta32:
619     appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
620               GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
621     appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
622                                                            ref.offsetInAtom(),
623               GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
624     break;
625   case negDelta32:
626     appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
627                                                            ref.offsetInAtom(),
628               GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
629     appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
630               GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
631     break;
632   case lazyPointer:
633   case lazyImmediateLocation:
634     llvm_unreachable("lazy reference kind implies Stubs pass was run");
635     break;
636   case invalid:
637     llvm_unreachable("unknown x86 Reference Kind");
638     break;
639   }
640 }
641 
642 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
643   return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
644 }
645 
646 } // namespace mach_o
647 } // namespace lld
648