blob: 4a22572363f375feaa5d0cb33d3672d2008e3bad [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 },
Nick Kledzik1bebb282014-09-09 23:52:59 +0000173 { false, 0, 0, 0 },
Nick Kledzik2458bec2014-07-16 19:49:02 +0000174
175 // Stub Helper size and code
176 10,
177 { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $lazy-info-offset
178 0xE9, 0x00, 0x00, 0x00, 0x00 }, // jmp helperhelper
179 { Reference::KindArch::x86, lazyImmediateLocation, 1, 0 },
180 { Reference::KindArch::x86, branch32, 6, 0 },
181
182 // Stub Helper-Common size and code
183 12,
184 { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $dyld_ImageLoaderCache
185 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *_fast_lazy_bind
186 0x90 }, // nop
187 { Reference::KindArch::x86, abs32, 1, 0 },
Nick Kledzik1bebb282014-09-09 23:52:59 +0000188 { false, 0, 0, 0 },
189 { Reference::KindArch::x86, abs32, 7, 0 },
190 { false, 0, 0, 0 }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000191};
192
193bool ArchHandler_x86::isCallSite(const Reference &ref) {
194 return (ref.kindValue() == branch32);
195}
196
197bool ArchHandler_x86::isPointer(const Reference &ref) {
198 return (ref.kindValue() == pointer32);
199}
200
201bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) {
202 if (!reloc.scattered)
203 return false;
204 return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) ||
205 (reloc.type == GENERIC_RELOC_SECTDIFF);
206}
207
208std::error_code
209ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
210 const DefinedAtom *inAtom,
211 uint32_t offsetInAtom,
212 uint64_t fixupAddress, bool swap,
213 FindAtomBySectionAndAddress atomFromAddress,
214 FindAtomBySymbolIndex atomFromSymbolIndex,
215 Reference::KindValue *kind,
216 const lld::Atom **target,
217 Reference::Addend *addend) {
218 typedef std::error_code E;
219 DefinedAtom::ContentPermissions perms;
220 const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
221 uint64_t targetAddress;
222 switch (relocPattern(reloc)) {
223 case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
224 // ex: call _foo (and _foo undefined)
225 *kind = branch32;
226 if (E ec = atomFromSymbolIndex(reloc.symbol, target))
227 return ec;
228 *addend = fixupAddress + 4 + readS32(swap, fixupContent);
229 break;
230 case GENERIC_RELOC_VANILLA | rPcRel | rLength4:
231 // ex: call _foo (and _foo defined)
232 *kind = branch32;
233 targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
234 return atomFromAddress(reloc.symbol, targetAddress, target, addend);
235 break;
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000236 case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
237 // ex: call _foo+n (and _foo defined)
238 *kind = branch32;
239 targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
240 if (E ec = atomFromAddress(0, reloc.value, target, addend))
241 return ec;
242 *addend = targetAddress - reloc.value;
243 break;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000244 case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
245 // ex: callw _foo (and _foo undefined)
246 *kind = branch16;
247 if (E ec = atomFromSymbolIndex(reloc.symbol, target))
248 return ec;
249 *addend = fixupAddress + 2 + readS16(swap, fixupContent);
250 break;
251 case GENERIC_RELOC_VANILLA | rPcRel | rLength2:
252 // ex: callw _foo (and _foo defined)
253 *kind = branch16;
254 targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
255 return atomFromAddress(reloc.symbol, targetAddress, target, addend);
256 break;
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000257 case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
258 // ex: callw _foo+n (and _foo defined)
259 *kind = branch16;
260 targetAddress = fixupAddress + 2 + readS16(swap, fixupContent);
261 if (E ec = atomFromAddress(0, reloc.value, target, addend))
262 return ec;
263 *addend = targetAddress - reloc.value;
264 break;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000265 case GENERIC_RELOC_VANILLA | rExtern | rLength4:
266 // ex: movl _foo, %eax (and _foo undefined)
267 // ex: .long _foo (and _foo undefined)
268 perms = inAtom->permissions();
269 *kind =
270 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
271 : pointer32;
272 if (E ec = atomFromSymbolIndex(reloc.symbol, target))
273 return ec;
274 *addend = readU32(swap, fixupContent);
275 break;
276 case GENERIC_RELOC_VANILLA | rLength4:
277 // ex: movl _foo, %eax (and _foo defined)
278 // ex: .long _foo (and _foo defined)
279 perms = inAtom->permissions();
280 *kind =
281 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
282 : pointer32;
283 targetAddress = readU32(swap, fixupContent);
284 return atomFromAddress(reloc.symbol, targetAddress, target, addend);
285 break;
Nick Kledzik7e246a42014-07-18 01:05:35 +0000286 case GENERIC_RELOC_VANILLA | rScattered | rLength4:
287 // ex: .long _foo+n (and _foo defined)
288 perms = inAtom->permissions();
289 *kind =
290 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
291 : pointer32;
292 if (E ec = atomFromAddress(0, reloc.value, target, addend))
293 return ec;
294 *addend = readU32(swap, fixupContent) - reloc.value;
295 break;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000296 default:
297 return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
298 }
299 return std::error_code();
300}
301
302std::error_code
303ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
304 const normalized::Relocation &reloc2,
305 const DefinedAtom *inAtom,
306 uint32_t offsetInAtom,
307 uint64_t fixupAddress, bool swap,
308 FindAtomBySectionAndAddress atomFromAddr,
309 FindAtomBySymbolIndex atomFromSymbolIndex,
310 Reference::KindValue *kind,
311 const lld::Atom **target,
312 Reference::Addend *addend) {
313 const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
314 std::error_code ec;
315 DefinedAtom::ContentPermissions perms = inAtom->permissions();
316 uint32_t fromAddress;
317 uint32_t toAddress;
318 uint32_t value;
319 const lld::Atom *fromTarget;
320 Reference::Addend offsetInTo;
321 Reference::Addend offsetInFrom;
322 switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
Nick Kledzik2d432352014-07-17 23:16:21 +0000323 case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
324 GENERIC_RELOC_PAIR | rScattered | rLength4):
325 case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
326 GENERIC_RELOC_PAIR | rScattered | rLength4):
Nick Kledzik2458bec2014-07-16 19:49:02 +0000327 toAddress = reloc1.value;
328 fromAddress = reloc2.value;
329 value = readS32(swap, fixupContent);
330 ec = atomFromAddr(0, toAddress, target, &offsetInTo);
331 if (ec)
332 return ec;
333 ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
334 if (ec)
335 return ec;
Nick Kledzik03e16f22014-07-21 22:06:57 +0000336 if (fromTarget != inAtom) {
337 if (*target != inAtom)
338 return make_dynamic_error_code(Twine("SECTDIFF relocation where "
339 "neither target is in atom"));
340 *kind = negDelta32;
341 *addend = toAddress - value - fromAddress;
342 *target = fromTarget;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000343 } else {
Nick Kledzik03e16f22014-07-21 22:06:57 +0000344 if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) {
345 // SECTDIFF relocations are used in i386 codegen where the function
346 // prolog does a CALL to the next instruction which POPs the return
347 // address into EBX which becomes the pic-base register. The POP
348 // instruction is label the used for the subtrahend in expressions.
349 // The funcRel32 kind represents the 32-bit delta to some symbol from
350 // the start of the function (atom) containing the funcRel32.
351 *kind = funcRel32;
352 uint32_t ta = fromAddress + value - toAddress;
353 *addend = ta - offsetInFrom;
354 } else {
355 *kind = delta32;
356 *addend = fromAddress + value - toAddress;
357 }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000358 }
359 return std::error_code();
360 break;
361 default:
362 return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
363 }
364}
365
Nick Kledzik2d432352014-07-17 23:16:21 +0000366void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
367 bool relocatable,
368 FindAddressForAtom findAddress,
369 uint8_t *atomContentBuffer) {
370 // Copy raw bytes.
371 memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
372 // Apply fix-ups.
373 for (const Reference *ref : atom) {
374 uint32_t offset = ref->offsetInAtom();
375 const Atom *target = ref->target();
376 uint64_t targetAddress = 0;
377 if (isa<DefinedAtom>(target))
378 targetAddress = findAddress(*target);
379 uint64_t atomAddress = findAddress(atom);
380 uint64_t fixupAddress = atomAddress + offset;
381 if (relocatable) {
382 applyFixupRelocatable(*ref, &atomContentBuffer[offset],
383 fixupAddress, targetAddress,
384 atomAddress);
385 } else {
386 applyFixupFinal(*ref, &atomContentBuffer[offset],
387 fixupAddress, targetAddress,
388 atomAddress);
389 }
390 }
391}
392
393void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *location,
394 uint64_t fixupAddress,
395 uint64_t targetAddress,
396 uint64_t inAtomAddress) {
397 if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
Nick Kledzik2458bec2014-07-16 19:49:02 +0000398 return;
Nick Kledzik2d432352014-07-17 23:16:21 +0000399 assert(ref.kindArch() == Reference::KindArch::x86);
Nick Kledzik2458bec2014-07-16 19:49:02 +0000400 int32_t *loc32 = reinterpret_cast<int32_t *>(location);
401 int16_t *loc16 = reinterpret_cast<int16_t *>(location);
Nick Kledzik2d432352014-07-17 23:16:21 +0000402 switch (ref.kindValue()) {
Nick Kledzik2458bec2014-07-16 19:49:02 +0000403 case branch32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000404 write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000405 break;
406 case branch16:
Nick Kledzik2d432352014-07-17 23:16:21 +0000407 write16(*loc16, _swap, (targetAddress - (fixupAddress + 2)) + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000408 break;
409 case pointer32:
410 case abs32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000411 write32(*loc32, _swap, targetAddress + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000412 break;
413 case funcRel32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000414 write32(*loc32, _swap, targetAddress - inAtomAddress + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000415 break;
416 case delta32:
Nick Kledzik2d432352014-07-17 23:16:21 +0000417 write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
Nick Kledzik2458bec2014-07-16 19:49:02 +0000418 break;
Nick Kledzik03e16f22014-07-21 22:06:57 +0000419 case negDelta32:
420 write32(*loc32, _swap, fixupAddress - targetAddress + ref.addend());
421 break;
Nick Kledzik21921372014-07-24 23:06:56 +0000422 case modeCode:
423 case modeData:
Nick Kledzik2458bec2014-07-16 19:49:02 +0000424 case lazyPointer:
425 case lazyImmediateLocation:
426 // do nothing
427 break;
428 default:
429 llvm_unreachable("invalid x86 Reference Kind");
430 break;
431 }
432}
433
Nick Kledzik2d432352014-07-17 23:16:21 +0000434void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
435 uint8_t *location,
436 uint64_t fixupAddress,
437 uint64_t targetAddress,
438 uint64_t inAtomAddress) {
439 int32_t *loc32 = reinterpret_cast<int32_t *>(location);
440 int16_t *loc16 = reinterpret_cast<int16_t *>(location);
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000441 bool useExternalReloc = useExternalRelocationTo(*ref.target());
Nick Kledzik2d432352014-07-17 23:16:21 +0000442 switch (ref.kindValue()) {
443 case branch32:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000444 if (useExternalReloc)
445 write32(*loc32, _swap, ref.addend() - (fixupAddress + 4));
446 else
447 write32(*loc32, _swap, (targetAddress - (fixupAddress+4)) + ref.addend());
Nick Kledzik2d432352014-07-17 23:16:21 +0000448 break;
449 case branch16:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000450 if (useExternalReloc)
451 write16(*loc16, _swap, ref.addend() - (fixupAddress + 2));
452 else
453 write16(*loc16, _swap, (targetAddress - (fixupAddress+2)) + ref.addend());
Nick Kledzik2d432352014-07-17 23:16:21 +0000454 break;
455 case pointer32:
456 case abs32:
457 write32(*loc32, _swap, targetAddress + ref.addend());
458 break;
459 case funcRel32:
460 write32(*loc32, _swap, targetAddress - inAtomAddress + ref.addend()); // FIXME
461 break;
462 case delta32:
463 write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
464 break;
Nick Kledzik03e16f22014-07-21 22:06:57 +0000465 case negDelta32:
466 write32(*loc32, _swap, fixupAddress - targetAddress + ref.addend());
467 break;
Nick Kledzik21921372014-07-24 23:06:56 +0000468 case modeCode:
469 case modeData:
Nick Kledzik2d432352014-07-17 23:16:21 +0000470 case lazyPointer:
471 case lazyImmediateLocation:
472 // do nothing
473 break;
474 default:
475 llvm_unreachable("invalid x86 Reference Kind");
476 break;
477 }
478}
479
480bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
481 // Undefined symbols are referenced via external relocations.
482 if (isa<UndefinedAtom>(&target))
483 return true;
484 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
485 switch (defAtom->merge()) {
486 case DefinedAtom::mergeAsTentative:
487 // Tentative definitions are referenced via external relocations.
488 return true;
489 case DefinedAtom::mergeAsWeak:
490 case DefinedAtom::mergeAsWeakAndAddressUsed:
491 // Global weak-defs are referenced via external relocations.
492 return (defAtom->scope() == DefinedAtom::scopeGlobal);
493 default:
494 break;
495 }
496 }
497 // Everything else is reference via an internal relocation.
498 return false;
499}
500
501
502void ArchHandler_x86::appendSectionRelocations(
503 const DefinedAtom &atom,
504 uint64_t atomSectionOffset,
505 const Reference &ref,
506 FindSymbolIndexForAtom symbolIndexForAtom,
507 FindSectionIndexForAtom sectionIndexForAtom,
508 FindAddressForAtom addressForAtom,
509 normalized::Relocations &relocs) {
510 if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
511 return;
512 assert(ref.kindArch() == Reference::KindArch::x86);
513 uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
514 bool useExternalReloc = useExternalRelocationTo(*ref.target());
515 switch (ref.kindValue()) {
Nick Kledzik21921372014-07-24 23:06:56 +0000516 case modeCode:
517 case modeData:
518 break;
Nick Kledzik2d432352014-07-17 23:16:21 +0000519 case branch32:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000520 if (useExternalReloc) {
521 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
522 GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength4);
523 } else {
524 if (ref.addend() != 0)
525 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
526 GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4);
527 else
528 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
529 GENERIC_RELOC_VANILLA | rPcRel | rLength4);
530 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000531 break;
532 case branch16:
Nick Kledzik68a1abd2014-07-18 00:37:52 +0000533 if (useExternalReloc) {
534 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
535 GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength2);
536 } else {
537 if (ref.addend() != 0)
538 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
539 GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2);
540 else
541 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
542 GENERIC_RELOC_VANILLA | rPcRel | rLength2);
543 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000544 break;
545 case pointer32:
546 case abs32:
547 if (useExternalReloc)
548 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
Nick Kledzik7e246a42014-07-18 01:05:35 +0000549 GENERIC_RELOC_VANILLA | rExtern | rLength4);
550 else {
551 if (ref.addend() != 0)
552 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
553 GENERIC_RELOC_VANILLA | rScattered | rLength4);
554 else
555 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
Nick Kledzik2d432352014-07-17 23:16:21 +0000556 GENERIC_RELOC_VANILLA | rLength4);
Nick Kledzik7e246a42014-07-18 01:05:35 +0000557 }
Nick Kledzik2d432352014-07-17 23:16:21 +0000558 break;
559 case funcRel32:
Nick Kledzik03e16f22014-07-21 22:06:57 +0000560 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
561 GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
562 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
563 GENERIC_RELOC_PAIR | rScattered | rLength4);
Nick Kledzik2d432352014-07-17 23:16:21 +0000564 break;
565 case delta32:
Nick Kledzik03e16f22014-07-21 22:06:57 +0000566 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
567 GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
568 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
569 ref.offsetInAtom(),
570 GENERIC_RELOC_PAIR | rScattered | rLength4);
571 break;
572 case negDelta32:
573 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
574 ref.offsetInAtom(),
575 GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
576 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
577 GENERIC_RELOC_PAIR | rScattered | rLength4);
Nick Kledzik2d432352014-07-17 23:16:21 +0000578 break;
579 case lazyPointer:
580 case lazyImmediateLocation:
581 llvm_unreachable("lazy reference kind implies Stubs pass was run");
582 break;
583 default:
584 llvm_unreachable("unknown x86 Reference Kind");
585 break;
586
587 }
588}
589
590
Nick Kledzik2458bec2014-07-16 19:49:02 +0000591std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
592 return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
593}
594
595} // namespace mach_o
596} // namespace lld