blob: eae3b0145b2f53754e08bfb2b4cd825594953ac0 [file] [log] [blame]
Nick Kledzik2458bec2014-07-16 19:49:02 +00001//===- 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
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/ADT/Triple.h"
17
18#include "llvm/Support/ErrorHandling.h"
19
20using namespace llvm::MachO;
21using namespace lld::mach_o::normalized;
22
23namespace lld {
24namespace mach_o {
25
26class ArchHandler_x86 : public ArchHandler {
27public:
28 ArchHandler_x86();
29 virtual ~ArchHandler_x86();
30
31 const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
32
33 Reference::KindArch kindArch() override { return Reference::KindArch::x86; }
34
35 const StubInfo &stubInfo() override { return _sStubInfo; }
36 bool isCallSite(const Reference &) override;
37 bool isPointer(const Reference &) override;
38 bool isPairedReloc(const normalized::Relocation &) override;
39 std::error_code getReferenceInfo(const normalized::Relocation &reloc,
40 const DefinedAtom *inAtom,
41 uint32_t offsetInAtom,
42 uint64_t fixupAddress, bool swap,
43 FindAtomBySectionAndAddress atomFromAddress,
44 FindAtomBySymbolIndex atomFromSymbolIndex,
45 Reference::KindValue *kind,
46 const lld::Atom **target,
47 Reference::Addend *addend) override;
48 std::error_code
49 getPairReferenceInfo(const normalized::Relocation &reloc1,
50 const normalized::Relocation &reloc2,
51 const DefinedAtom *inAtom,
52 uint32_t offsetInAtom,
53 uint64_t fixupAddress, bool swap,
54 FindAtomBySectionAndAddress atomFromAddress,
55 FindAtomBySymbolIndex atomFromSymbolIndex,
56 Reference::KindValue *kind,
57 const lld::Atom **target,
58 Reference::Addend *addend) override;
59
Nick Kledzik2d432352014-07-17 23:16:21 +000060 void generateAtomContent(const DefinedAtom &atom, bool relocatable,
61 FindAddressForAtom findAddress,
62 uint8_t *atomContentBuffer) override;
63
64 void appendSectionRelocations(const DefinedAtom &atom,
65 uint64_t atomSectionOffset,
66 const Reference &ref,
67 FindSymbolIndexForAtom symbolIndexForAtom,
68 FindSectionIndexForAtom sectionIndexForAtom,
69 FindAddressForAtom addressForAtom,
70 normalized::Relocations &relocs) override;
Nick Kledzik2458bec2014-07-16 19:49:02 +000071
Nick Kledzik21921372014-07-24 23:06:56 +000072 bool isDataInCodeTransition(Reference::KindValue refKind) override {
73 switch (refKind) {
74 case modeCode:
75 case modeData:
76 return true;
77 default:
78 return false;
79 break;
80 }
81 }
82
83 Reference::KindValue dataInCodeTransitionStart(
84 const MachODefinedAtom &atom) override {
85 return modeData;
86 }
87
88 Reference::KindValue dataInCodeTransitionEnd(
89 const MachODefinedAtom &atom) override {
90 return modeCode;
91 }
92
Nick Kledzik2458bec2014-07-16 19:49:02 +000093private:
94 static const Registry::KindStrings _sKindStrings[];
95 static const StubInfo _sStubInfo;
96
97 enum : Reference::KindValue {
98 invalid, /// for error condition
99
Nick Kledzik21921372014-07-24 23:06:56 +0000100 modeCode, /// Content starting at this offset is code.
101 modeData, /// Content starting at this offset is data.
102
Nick Kledzik2458bec2014-07-16 19:49:02 +0000103 // Kinds found in mach-o .o files:
104 branch32, /// ex: call _foo
105 branch16, /// ex: callw _foo
106 abs32, /// ex: movl _foo, %eax
107 funcRel32, /// ex: movl _foo-L1(%eax), %eax
108 pointer32, /// ex: .long _foo
109 delta32, /// ex: .long _foo - .
Nick Kledzik03e16f22014-07-21 22:06:57 +0000110 negDelta32, /// ex: .long . - _foo
Nick Kledzik2458bec2014-07-16 19:49:02 +0000111
112 // Kinds introduced by Passes:
113 lazyPointer, /// Location contains a lazy pointer.
114 lazyImmediateLocation, /// Location contains immediate value used in stub.
115 };
116
Nick Kledzik2d432352014-07-17 23:16:21 +0000117 static bool useExternalRelocationTo(const Atom &target);
118
119 void applyFixupFinal(const Reference &ref, uint8_t *location,
120 uint64_t fixupAddress, uint64_t targetAddress,
121 uint64_t inAtomAddress);
122
123 void applyFixupRelocatable(const Reference &ref, uint8_t *location,
124 uint64_t fixupAddress,
125 uint64_t targetAddress,
126 uint64_t inAtomAddress);
127
Nick Kledzik2458bec2014-07-16 19:49:02 +0000128 const bool _swap;
129};
130
131//===----------------------------------------------------------------------===//
132// ArchHandler_x86
133//===----------------------------------------------------------------------===//
134
135ArchHandler_x86::ArchHandler_x86() :
136 _swap(!MachOLinkingContext::isHostEndian(MachOLinkingContext::arch_x86)) {}
137
138ArchHandler_x86::~ArchHandler_x86() { }
139
140const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = {
141 LLD_KIND_STRING_ENTRY(invalid),
Nick Kledzik21921372014-07-24 23:06:56 +0000142 LLD_KIND_STRING_ENTRY(modeCode),
143 LLD_KIND_STRING_ENTRY(modeData),
Nick Kledzik2458bec2014-07-16 19:49:02 +0000144 LLD_KIND_STRING_ENTRY(branch32),
145 LLD_KIND_STRING_ENTRY(branch16),
146 LLD_KIND_STRING_ENTRY(abs32),
147 LLD_KIND_STRING_ENTRY(funcRel32),
148 LLD_KIND_STRING_ENTRY(pointer32),
149 LLD_KIND_STRING_ENTRY(delta32),
Nick Kledzik03e16f22014-07-21 22:06:57 +0000150 LLD_KIND_STRING_ENTRY(negDelta32),
Nick Kledzik2458bec2014-07-16 19:49:02 +0000151 LLD_KIND_STRING_ENTRY(lazyPointer),
152 LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
153 LLD_KIND_STRING_END
154};
155
156const ArchHandler::StubInfo ArchHandler_x86::_sStubInfo = {
157 "dyld_stub_binder",
158
159 // Lazy pointer references
160 { Reference::KindArch::x86, pointer32, 0, 0 },
161 { Reference::KindArch::x86, lazyPointer, 0, 0 },
162
163 // GOT pointer to dyld_stub_binder
164 { Reference::KindArch::x86, pointer32, 0, 0 },
165
166 // x86 code alignment
167 1,
168
169 // Stub size and code
170 6,
171 { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }, // jmp *lazyPointer
172 { Reference::KindArch::x86, abs32, 2, 0 },
173
174 // Stub Helper size and code
175 10,
176 { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $lazy-info-offset
177 0xE9, 0x00, 0x00, 0x00, 0x00 }, // jmp helperhelper
178 { Reference::KindArch::x86, lazyImmediateLocation, 1, 0 },
179 { Reference::KindArch::x86, branch32, 6, 0 },
180
181 // Stub Helper-Common size and code
182 12,
183 { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $dyld_ImageLoaderCache
184 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *_fast_lazy_bind
185 0x90 }, // nop
186 { Reference::KindArch::x86, abs32, 1, 0 },
187 { Reference::KindArch::x86, abs32, 7, 0 }
188};
189
190bool ArchHandler_x86::isCallSite(const Reference &ref) {
191 return (ref.kindValue() == branch32);
192}
193
194bool ArchHandler_x86::isPointer(const Reference &ref) {
195 return (ref.kindValue() == pointer32);
196}
197
198bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) {
199 if (!reloc.scattered)
200 return false;
201 return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) ||
202 (reloc.type == GENERIC_RELOC_SECTDIFF);
203}
204
205std::error_code
206ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
207 const DefinedAtom *inAtom,
208 uint32_t offsetInAtom,
209 uint64_t fixupAddress, bool swap,
210 FindAtomBySectionAndAddress atomFromAddress,
211 FindAtomBySymbolIndex atomFromSymbolIndex,
212 Reference::KindValue *kind,
213 const lld::Atom **target,
214 Reference::Addend *addend) {
215 typedef std::error_code E;
216 DefinedAtom::ContentPermissions perms;
217 const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
218 uint64_t targetAddress;
219 switch (relocPattern(reloc)) {
220 case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
221 // ex: call _foo (and _foo undefined)
222 *kind = branch32;
223 if (E ec = atomFromSymbolIndex(reloc.symbol, target))
224 return ec;
225 *addend = fixupAddress + 4 + readS32(swap, fixupContent);
226 break;
227 case GENERIC_RELOC_VANILLA | rPcRel | rLength4:
228 // ex: call _foo (and _foo defined)
229 *kind = branch32;
230 targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
231 return atomFromAddress(reloc.symbol, targetAddress, target, addend);
232 break;
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000233 case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
234 // ex: call _foo+n (and _foo defined)
235 *kind = branch32;
236 targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
237 if (E ec = atomFromAddress(0, reloc.value, target, addend))
238 return ec;
239 *addend = targetAddress - reloc.value;
240 break;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000241 case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
242 // ex: callw _foo (and _foo undefined)
243 *kind = branch16;
244 if (E ec = atomFromSymbolIndex(reloc.symbol, target))
245 return ec;
246 *addend = fixupAddress + 2 + readS16(swap, fixupContent);
247 break;
248 case GENERIC_RELOC_VANILLA | rPcRel | rLength2:
249 // ex: callw _foo (and _foo defined)
250 *kind = branch16;
251 targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
252 return atomFromAddress(reloc.symbol, targetAddress, target, addend);
253 break;
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000254 case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
255 // ex: callw _foo+n (and _foo defined)
256 *kind = branch16;
257 targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
258 if (E ec = atomFromAddress(0, reloc.value, target, addend))
259 return ec;
260 *addend = targetAddress - reloc.value;
261 break;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000262 case GENERIC_RELOC_VANILLA | rExtern | rLength4:
263 // ex: movl _foo, %eax (and _foo undefined)
264 // ex: .long _foo (and _foo undefined)
265 perms = inAtom->permissions();
266 *kind =
267 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
268 : pointer32;
269 if (E ec = atomFromSymbolIndex(reloc.symbol, target))
270 return ec;
271 *addend = readU32(swap, fixupContent);
272 break;
273 case GENERIC_RELOC_VANILLA | rLength4:
274 // ex: movl _foo, %eax (and _foo defined)
275 // ex: .long _foo (and _foo defined)
276 perms = inAtom->permissions();
277 *kind =
278 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
279 : pointer32;
280 targetAddress = readU32(swap, fixupContent);
281 return atomFromAddress(reloc.symbol, targetAddress, target, addend);
282 break;
Nick Kledzik7e246a42014-07-18 01:05:35 +0000283 case GENERIC_RELOC_VANILLA | rScattered | rLength4:
284 // ex: .long _foo+n (and _foo defined)
285 perms = inAtom->permissions();
286 *kind =
287 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
288 : pointer32;
289 if (E ec = atomFromAddress(0, reloc.value, target, addend))
290 return ec;
291 *addend = readU32(swap, fixupContent) - reloc.value;
292 break;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000293 default:
294 return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
295 }
296 return std::error_code();
297}
298
299std::error_code
300ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
301 const normalized::Relocation &reloc2,
302 const DefinedAtom *inAtom,
303 uint32_t offsetInAtom,
304 uint64_t fixupAddress, bool swap,
305 FindAtomBySectionAndAddress atomFromAddr,
306 FindAtomBySymbolIndex atomFromSymbolIndex,
307 Reference::KindValue *kind,
308 const lld::Atom **target,
309 Reference::Addend *addend) {
310 const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
311 std::error_code ec;
312 DefinedAtom::ContentPermissions perms = inAtom->permissions();
313 uint32_t fromAddress;
314 uint32_t toAddress;
315 uint32_t value;
316 const lld::Atom *fromTarget;
317 Reference::Addend offsetInTo;
318 Reference::Addend offsetInFrom;
319 switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000320 case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
321 GENERIC_RELOC_PAIR | rScattered | rLength4):
322 case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
323 GENERIC_RELOC_PAIR | rScattered | rLength4):
Nick Kledzik2458bec2014-07-16 19:49:02 +0000324 toAddress = reloc1.value;
325 fromAddress = reloc2.value;
326 value = readS32(swap, fixupContent);
327 ec = atomFromAddr(0, toAddress, target, &offsetInTo);
328 if (ec)
329 return ec;
330 ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
331 if (ec)
332 return ec;
Nick Kledzik03e16f22014-07-21 22:06:57 +0000333 if (fromTarget != inAtom) {
334 if (*target != inAtom)
335 return make_dynamic_error_code(Twine("SECTDIFF relocation where "
336 "neither target is in atom"));
337 *kind = negDelta32;
338 *addend = toAddress - value - fromAddress;
339 *target = fromTarget;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000340 } else {
Nick Kledzik03e16f22014-07-21 22:06:57 +0000341 if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) {
342 // SECTDIFF relocations are used in i386 codegen where the function
343 // prolog does a CALL to the next instruction which POPs the return
344 // address into EBX which becomes the pic-base register. The POP
345 // instruction is label the used for the subtrahend in expressions.
346 // The funcRel32 kind represents the 32-bit delta to some symbol from
347 // the start of the function (atom) containing the funcRel32.
348 *kind = funcRel32;
349 uint32_t ta = fromAddress + value - toAddress;
350 *addend = ta - offsetInFrom;
351 } else {
352 *kind = delta32;
353 *addend = fromAddress + value - toAddress;
354 }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000355 }
356 return std::error_code();
357 break;
358 default:
359 return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
360 }
361}
362
Nick Kledzik2d432352014-07-17 23:16:21 +0000363void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
364 bool relocatable,
365 FindAddressForAtom findAddress,
366 uint8_t *atomContentBuffer) {
367 // Copy raw bytes.
368 memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
369 // Apply fix-ups.
370 for (const Reference *ref : atom) {
371 uint32_t offset = ref->offsetInAtom();
372 const Atom *target = ref->target();
373 uint64_t targetAddress = 0;
374 if (isa<DefinedAtom>(target))
375 targetAddress = findAddress(*target);
376 uint64_t atomAddress = findAddress(atom);
377 uint64_t fixupAddress = atomAddress + offset;
378 if (relocatable) {
379 applyFixupRelocatable(*ref, &atomContentBuffer[offset],
380 fixupAddress, targetAddress,
381 atomAddress);
382 } else {
383 applyFixupFinal(*ref, &atomContentBuffer[offset],
384 fixupAddress, targetAddress,
385 atomAddress);
386 }
387 }
388}
389
390void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *location,
391 uint64_t fixupAddress,
392 uint64_t targetAddress,
393 uint64_t inAtomAddress) {
394 if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
Nick Kledzik2458bec2014-07-16 19:49:02 +0000395 return;
Nick Kledzik2d432352014-07-17 23:16:21 +0000396 assert(ref.kindArch() == Reference::KindArch::x86);
Nick Kledzik2458bec2014-07-16 19:49:02 +0000397 int32_t *loc32 = reinterpret_cast<int32_t *>(location);
398 int16_t *loc16 = reinterpret_cast<int16_t *>(location);
Nick Kledzik2d432352014-07-17 23:16:21 +0000399 switch (ref.kindValue()) {
Nick Kledzik2458bec2014-07-16 19:49:02 +0000400 case branch32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000401 write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000402 break;
403 case branch16:
Nick Kledzik2d432352014-07-17 23:16:21 +0000404 write16(*loc16, _swap, (targetAddress - (fixupAddress + 2)) + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000405 break;
406 case pointer32:
407 case abs32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000408 write32(*loc32, _swap, targetAddress + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000409 break;
410 case funcRel32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000411 write32(*loc32, _swap, targetAddress - inAtomAddress + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000412 break;
413 case delta32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000414 write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000415 break;
Nick Kledzik03e16f22014-07-21 22:06:57 +0000416 case negDelta32:
417 write32(*loc32, _swap, fixupAddress - targetAddress + ref.addend());
418 break;
Nick Kledzik21921372014-07-24 23:06:56 +0000419 case modeCode:
420 case modeData:
Nick Kledzik2458bec2014-07-16 19:49:02 +0000421 case lazyPointer:
422 case lazyImmediateLocation:
423 // do nothing
424 break;
425 default:
426 llvm_unreachable("invalid x86 Reference Kind");
427 break;
428 }
429}
430
Nick Kledzik2d432352014-07-17 23:16:21 +0000431void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
432 uint8_t *location,
433 uint64_t fixupAddress,
434 uint64_t targetAddress,
435 uint64_t inAtomAddress) {
436 int32_t *loc32 = reinterpret_cast<int32_t *>(location);
437 int16_t *loc16 = reinterpret_cast<int16_t *>(location);
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000438 bool useExternalReloc = useExternalRelocationTo(*ref.target());
Nick Kledzik2d432352014-07-17 23:16:21 +0000439 switch (ref.kindValue()) {
440 case branch32:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000441 if (useExternalReloc)
442 write32(*loc32, _swap, ref.addend() - (fixupAddress + 4));
443 else
444 write32(*loc32, _swap, (targetAddress - (fixupAddress+4)) + ref.addend());
Nick Kledzik2d432352014-07-17 23:16:21 +0000445 break;
446 case branch16:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000447 if (useExternalReloc)
448 write16(*loc16, _swap, ref.addend() - (fixupAddress + 2));
449 else
450 write16(*loc16, _swap, (targetAddress - (fixupAddress+2)) + ref.addend());
Nick Kledzik2d432352014-07-17 23:16:21 +0000451 break;
452 case pointer32:
453 case abs32:
454 write32(*loc32, _swap, targetAddress + ref.addend());
455 break;
456 case funcRel32:
457 write32(*loc32, _swap, targetAddress - inAtomAddress + ref.addend()); // FIXME
458 break;
459 case delta32:
460 write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
461 break;
Nick Kledzik03e16f22014-07-21 22:06:57 +0000462 case negDelta32:
463 write32(*loc32, _swap, fixupAddress - targetAddress + ref.addend());
464 break;
Nick Kledzik21921372014-07-24 23:06:56 +0000465 case modeCode:
466 case modeData:
Nick Kledzik2d432352014-07-17 23:16:21 +0000467 case lazyPointer:
468 case lazyImmediateLocation:
469 // do nothing
470 break;
471 default:
472 llvm_unreachable("invalid x86 Reference Kind");
473 break;
474 }
475}
476
477bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
478 // Undefined symbols are referenced via external relocations.
479 if (isa<UndefinedAtom>(&target))
480 return true;
481 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
482 switch (defAtom->merge()) {
483 case DefinedAtom::mergeAsTentative:
484 // Tentative definitions are referenced via external relocations.
485 return true;
486 case DefinedAtom::mergeAsWeak:
487 case DefinedAtom::mergeAsWeakAndAddressUsed:
488 // Global weak-defs are referenced via external relocations.
489 return (defAtom->scope() == DefinedAtom::scopeGlobal);
490 default:
491 break;
492 }
493 }
494 // Everything else is reference via an internal relocation.
495 return false;
496}
497
498
499void ArchHandler_x86::appendSectionRelocations(
500 const DefinedAtom &atom,
501 uint64_t atomSectionOffset,
502 const Reference &ref,
503 FindSymbolIndexForAtom symbolIndexForAtom,
504 FindSectionIndexForAtom sectionIndexForAtom,
505 FindAddressForAtom addressForAtom,
506 normalized::Relocations &relocs) {
507 if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
508 return;
509 assert(ref.kindArch() == Reference::KindArch::x86);
510 uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
511 bool useExternalReloc = useExternalRelocationTo(*ref.target());
512 switch (ref.kindValue()) {
Nick Kledzik21921372014-07-24 23:06:56 +0000513 case modeCode:
514 case modeData:
515 break;
Nick Kledzik2d432352014-07-17 23:16:21 +0000516 case branch32:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000517 if (useExternalReloc) {
518 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
519 GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength4);
520 } else {
521 if (ref.addend() != 0)
522 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
523 GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4);
524 else
525 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
526 GENERIC_RELOC_VANILLA | rPcRel | rLength4);
527 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000528 break;
529 case branch16:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000530 if (useExternalReloc) {
531 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
532 GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength2);
533 } else {
534 if (ref.addend() != 0)
535 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
536 GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2);
537 else
538 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
539 GENERIC_RELOC_VANILLA | rPcRel | rLength2);
540 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000541 break;
542 case pointer32:
543 case abs32:
544 if (useExternalReloc)
545 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
Nick Kledzik7e246a42014-07-18 01:05:35 +0000546 GENERIC_RELOC_VANILLA | rExtern | rLength4);
547 else {
548 if (ref.addend() != 0)
549 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
550 GENERIC_RELOC_VANILLA | rScattered | rLength4);
551 else
552 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
Nick Kledzik2d432352014-07-17 23:16:21 +0000553 GENERIC_RELOC_VANILLA | rLength4);
Nick Kledzik7e246a42014-07-18 01:05:35 +0000554 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000555 break;
556 case funcRel32:
Nick Kledzik03e16f22014-07-21 22:06:57 +0000557 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
558 GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
559 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
560 GENERIC_RELOC_PAIR | rScattered | rLength4);
Nick Kledzik2d432352014-07-17 23:16:21 +0000561 break;
562 case delta32:
Nick Kledzik03e16f22014-07-21 22:06:57 +0000563 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
564 GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
565 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
566 ref.offsetInAtom(),
567 GENERIC_RELOC_PAIR | rScattered | rLength4);
568 break;
569 case negDelta32:
570 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
571 ref.offsetInAtom(),
572 GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
573 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
574 GENERIC_RELOC_PAIR | rScattered | rLength4);
Nick Kledzik2d432352014-07-17 23:16:21 +0000575 break;
576 case lazyPointer:
577 case lazyImmediateLocation:
578 llvm_unreachable("lazy reference kind implies Stubs pass was run");
579 break;
580 default:
581 llvm_unreachable("unknown x86 Reference Kind");
582 break;
583
584 }
585}
586
587
Nick Kledzik2458bec2014-07-16 19:49:02 +0000588std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
589 return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
590}
591
592} // namespace mach_o
593} // namespace lld