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