Coverage Report

Created: 2019-01-21 03:01

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