Coverage Report

Created: 2019-05-22 02:55

/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
23
  ArchHandler_x86() = default;
33
23
  ~ArchHandler_x86() override = default;
34
35
16
  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
36
37
50
  Reference::KindArch kindArch() override { return Reference::KindArch::x86; }
38
39
15
  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
1
  bool needsCompactUnwind() override {
49
1
    return false;
50
1
  }
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
2
  Reference::KindValue unwindRefToCIEKind() override {
65
2
    return negDelta32;
66
2
  }
67
68
2
  Reference::KindValue unwindRefToFunctionKind() override{
69
2
    return delta32;
70
2
  }
71
72
1
  Reference::KindValue lazyImmediateLocationKind() override {
73
1
    return lazyImmediateLocation;
74
1
  }
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
43
  bool isDataInCodeTransition(Reference::KindValue refKind) override {
124
43
    return refKind == modeCode || 
refKind == modeData41
;
125
43
  }
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
2
bool ArchHandler_x86::isCallSite(const Reference &ref) {
236
2
  return (ref.kindValue() == branch32);
237
2
}
238
239
11
bool ArchHandler_x86::isPointer(const Reference &ref) {
240
11
  return (ref.kindValue() == pointer32);
241
11
}
242
243
28
bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) {
244
28
  if (!reloc.scattered)
245
14
    return false;
246
14
  return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) ||
247
14
         
(reloc.type == GENERIC_RELOC_SECTDIFF)6
;
248
14
}
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
18
                                  Reference::Addend *addend) {
260
18
  DefinedAtom::ContentPermissions perms;
261
18
  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
262
18
  uint64_t targetAddress;
263
18
  switch (relocPattern(reloc)) {
264
18
  case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
265
5
    // ex: call _foo (and _foo undefined)
266
5
    *kind = branch32;
267
5
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
268
0
      return ec;
269
5
    *addend = fixupAddress + 4 + (int32_t)*(const little32_t *)fixupContent;
270
5
    break;
271
5
  case GENERIC_RELOC_VANILLA | rPcRel | rLength4:
272
2
    // ex: call _foo (and _foo defined)
273
2
    *kind = branch32;
274
2
    targetAddress =
275
2
        fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
276
2
    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
277
5
    
break0
;
278
5
  case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
279
1
    // ex: call _foo+n (and _foo defined)
280
1
    *kind = branch32;
281
1
    targetAddress =
282
1
        fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
283
1
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
284
0
      return ec;
285
1
    *addend = targetAddress - reloc.value;
286
1
    break;
287
1
  case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
288
1
    // ex: callw _foo (and _foo undefined)
289
1
    *kind = branch16;
290
1
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
291
0
      return ec;
292
1
    *addend = fixupAddress + 2 + (int16_t)*(const little16_t *)fixupContent;
293
1
    break;
294
1
  case GENERIC_RELOC_VANILLA | rPcRel | rLength2:
295
1
    // ex: callw _foo (and _foo defined)
296
1
    *kind = branch16;
297
1
    targetAddress =
298
1
        fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
299
1
    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
300
1
    
break0
;
301
1
  case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
302
1
    // ex: callw _foo+n (and _foo defined)
303
1
    *kind = branch16;
304
1
    targetAddress =
305
1
        fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
306
1
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
307
0
      return ec;
308
1
    *addend = targetAddress - reloc.value;
309
1
    break;
310
3
  case GENERIC_RELOC_VANILLA | rExtern | rLength4:
311
3
    // ex: movl _foo, %eax   (and _foo undefined)
312
3
    // ex: .long _foo        (and _foo undefined)
313
3
    perms = inAtom->permissions();
314
3
    *kind =
315
3
        ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? 
abs321
316
3
                                                                 : 
pointer322
;
317
3
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
318
0
      return ec;
319
3
    *addend = *(const ulittle32_t *)fixupContent;
320
3
    break;
321
3
  case GENERIC_RELOC_VANILLA | rLength4:
322
2
    // ex: movl _foo, %eax   (and _foo defined)
323
2
    // ex: .long _foo        (and _foo defined)
324
2
    perms = inAtom->permissions();
325
2
    *kind =
326
2
        ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? 
abs321
327
2
                                                                 : 
pointer321
;
328
2
    targetAddress = *(const ulittle32_t *)fixupContent;
329
2
    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
330
3
    
break0
;
331
3
  case GENERIC_RELOC_VANILLA | rScattered | rLength4:
332
2
    // ex: .long _foo+n      (and _foo defined)
333
2
    perms = inAtom->permissions();
334
2
    *kind =
335
2
        ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? 
abs321
336
2
                                                                 : 
pointer321
;
337
2
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
338
0
      return ec;
339
2
    *addend = *(const ulittle32_t *)fixupContent - reloc.value;
340
2
    break;
341
2
  default:
342
0
    return llvm::make_error<GenericError>("unsupported i386 relocation type");
343
13
  }
344
13
  return llvm::Error::success();
345
13
}
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
10
                                      Reference::Addend *addend) {
359
10
  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
360
10
  DefinedAtom::ContentPermissions perms = inAtom->permissions();
361
10
  uint32_t fromAddress;
362
10
  uint32_t toAddress;
363
10
  uint32_t value;
364
10
  const lld::Atom *fromTarget;
365
10
  Reference::Addend offsetInTo;
366
10
  Reference::Addend offsetInFrom;
367
10
  switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
368
10
  case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
369
10
         GENERIC_RELOC_PAIR | rScattered | rLength4):
370
10
  case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
371
10
         GENERIC_RELOC_PAIR | rScattered | rLength4):
372
10
    toAddress = reloc1.value;
373
10
    fromAddress = reloc2.value;
374
10
    value = *(const little32_t *)fixupContent;
375
10
    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
376
0
      return ec;
377
10
    if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
378
0
      return ec;
379
10
    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
8
    } else {
387
8
      if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) {
388
4
        // SECTDIFF relocations are used in i386 codegen where the function
389
4
        // prolog does a CALL to the next instruction which POPs the return
390
4
        // address into EBX which becomes the pic-base register.  The POP
391
4
        // instruction is label the used for the subtrahend in expressions.
392
4
        // The funcRel32 kind represents the 32-bit delta to some symbol from
393
4
        // the start of the function (atom) containing the funcRel32.
394
4
        *kind = funcRel32;
395
4
        uint32_t ta = fromAddress + value - toAddress;
396
4
        *addend = ta - offsetInFrom;
397
4
      } else {
398
4
        *kind = delta32;
399
4
        *addend = fromAddress + value - toAddress;
400
4
      }
401
8
    }
402
10
    return llvm::Error::success();
403
10
    
break0
;
404
10
  default:
405
0
    return llvm::make_error<GenericError>("unsupported i386 relocation type");
406
10
  }
407
10
}
408
409
void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
410
                                          bool relocatable,
411
                                          FindAddressForAtom findAddress,
412
                                          FindAddressForAtom findSectionAddress,
413
                                          uint64_t imageBaseAddress,
414
23
                            llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
415
23
  // Copy raw bytes.
416
23
  std::copy(atom.rawContent().begin(), atom.rawContent().end(),
417
23
            atomContentBuffer.begin());
418
23
  // Apply fix-ups.
419
43
  for (const Reference *ref : atom) {
420
43
    uint32_t offset = ref->offsetInAtom();
421
43
    const Atom *target = ref->target();
422
43
    uint64_t targetAddress = 0;
423
43
    if (isa<DefinedAtom>(target))
424
33
      targetAddress = findAddress(*target);
425
43
    uint64_t atomAddress = findAddress(atom);
426
43
    uint64_t fixupAddress = atomAddress + offset;
427
43
    if (relocatable) {
428
32
      applyFixupRelocatable(*ref, &atomContentBuffer[offset],
429
32
                                        fixupAddress, targetAddress,
430
32
                                        atomAddress);
431
32
    } else {
432
11
      applyFixupFinal(*ref, &atomContentBuffer[offset],
433
11
                                  fixupAddress, targetAddress,
434
11
                                  atomAddress);
435
11
    }
436
43
  }
437
23
}
438
439
void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *loc,
440
                                      uint64_t fixupAddress,
441
                                      uint64_t targetAddress,
442
11
                                      uint64_t inAtomAddress) {
443
11
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
444
0
    return;
445
11
  assert(ref.kindArch() == Reference::KindArch::x86);
446
11
  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
447
11
  switch (static_cast<X86Kind>(ref.kindValue())) {
448
11
  case branch32:
449
2
    *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
450
2
    break;
451
11
  case branch16:
452
0
    *loc32 = (targetAddress - (fixupAddress + 2)) + ref.addend();
453
0
    break;
454
11
  case pointer32:
455
5
  case abs32:
456
5
    *loc32 = targetAddress + ref.addend();
457
5
    break;
458
5
  case funcRel32:
459
1
    *loc32 = targetAddress - inAtomAddress + ref.addend();
460
1
    break;
461
5
  case delta32:
462
0
    *loc32 = targetAddress - fixupAddress + ref.addend();
463
0
    break;
464
5
  case negDelta32:
465
0
    *loc32 = fixupAddress - targetAddress + ref.addend();
466
0
    break;
467
5
  case modeCode:
468
1
  case modeData:
469
1
  case lazyPointer:
470
1
    // do nothing
471
1
    break;
472
2
  case lazyImmediateLocation:
473
2
    *loc32 = ref.addend();
474
2
    break;
475
1
  case invalid:
476
0
    llvm_unreachable("invalid x86 Reference Kind");
477
1
    
break0
;
478
11
  }
479
11
}
480
481
void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
482
                                               uint8_t *loc,
483
                                               uint64_t fixupAddress,
484
                                               uint64_t targetAddress,
485
32
                                               uint64_t inAtomAddress) {
486
32
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
487
0
    return;
488
32
  assert(ref.kindArch() == Reference::KindArch::x86);
489
32
  bool useExternalReloc = useExternalRelocationTo(*ref.target());
490
32
  ulittle16_t *loc16 = reinterpret_cast<ulittle16_t *>(loc);
491
32
  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
492
32
  switch (static_cast<X86Kind>(ref.kindValue())) {
493
32
  case branch32:
494
7
    if (useExternalReloc)
495
4
      *loc32 = ref.addend() - (fixupAddress + 4);
496
3
    else
497
3
      *loc32  =(targetAddress - (fixupAddress+4)) + ref.addend();
498
7
    break;
499
32
  case branch16:
500
3
    if (useExternalReloc)
501
1
      *loc16 = ref.addend() - (fixupAddress + 2);
502
2
    else
503
2
      *loc16 = (targetAddress - (fixupAddress+2)) + ref.addend();
504
3
    break;
505
32
  case pointer32:
506
7
  case abs32:
507
7
    *loc32 = targetAddress + ref.addend();
508
7
    break;
509
7
  case funcRel32:
510
3
    *loc32 = targetAddress - inAtomAddress + ref.addend(); // FIXME
511
3
    break;
512
7
  case delta32:
513
4
    *loc32 = targetAddress - fixupAddress + ref.addend();
514
4
    break;
515
7
  case negDelta32:
516
2
    *loc32 = fixupAddress - targetAddress + ref.addend();
517
2
    break;
518
7
  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
32
  }
528
32
}
529
530
60
bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
531
60
  // Undefined symbols are referenced via external relocations.
532
60
  if (isa<UndefinedAtom>(&target))
533
16
    return true;
534
44
  if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
535
44
     switch (defAtom->merge()) {
536
44
     case DefinedAtom::mergeAsTentative:
537
0
       // Tentative definitions are referenced via external relocations.
538
0
       return true;
539
44
     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
44
     default:
544
44
       break;
545
44
    }
546
44
  }
547
44
  // Everything else is reference via an internal relocation.
548
44
  return false;
549
44
}
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
28
                                   normalized::Relocations &relocs) {
559
28
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
560
0
    return;
561
28
  assert(ref.kindArch() == Reference::KindArch::x86);
562
28
  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
563
28
  bool useExternalReloc = useExternalRelocationTo(*ref.target());
564
28
  switch (static_cast<X86Kind>(ref.kindValue())) {
565
28
  case modeCode:
566
6
  case modeData:
567
6
    break;
568
7
  case branch32:
569
7
    if (useExternalReloc) {
570
4
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
571
4
                  GENERIC_RELOC_VANILLA | rExtern    | rPcRel | rLength4);
572
4
    } else {
573
3
      if (ref.addend() != 0)
574
1
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
575
1
                  GENERIC_RELOC_VANILLA | rScattered | rPcRel |  rLength4);
576
2
      else
577
2
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
578
2
                  GENERIC_RELOC_VANILLA |              rPcRel | rLength4);
579
3
    }
580
7
    break;
581
6
  case branch16:
582
3
    if (useExternalReloc) {
583
1
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
584
1
                  GENERIC_RELOC_VANILLA | rExtern    | rPcRel | rLength2);
585
2
    } else {
586
2
      if (ref.addend() != 0)
587
1
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
588
1
                  GENERIC_RELOC_VANILLA | rScattered | rPcRel |  rLength2);
589
1
      else
590
1
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
591
1
                  GENERIC_RELOC_VANILLA |              rPcRel | rLength2);
592
2
    }
593
3
    break;
594
7
  case pointer32:
595
7
  case abs32:
596
7
    if (useExternalReloc)
597
3
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
598
3
                GENERIC_RELOC_VANILLA |    rExtern     |  rLength4);
599
4
    else {
600
4
      if (ref.addend() != 0)
601
2
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
602
2
                GENERIC_RELOC_VANILLA |    rScattered  |  rLength4);
603
2
      else
604
2
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
605
2
                GENERIC_RELOC_VANILLA |                   rLength4);
606
4
    }
607
7
    break;
608
7
  case funcRel32:
609
3
    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
610
3
              GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
611
3
    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
612
3
              GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
613
3
    break;
614
7
  case delta32:
615
2
    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
616
2
              GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
617
2
    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
618
2
                                                           ref.offsetInAtom(),
619
2
              GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
620
2
    break;
621
7
  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
7
  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
28
  }
636
28
}
637
638
23
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
639
23
  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
640
23
}
641
642
} // namespace mach_o
643
} // namespace lld