Coverage Report

Created: 2017-09-19 22:28

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- lib/FileFormat/MachO/ArchHandler_arm.cpp ---------------------------===//
2
//
3
//                             The LLVM Linker
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "ArchHandler.h"
11
#include "Atoms.h"
12
#include "MachONormalizedFileBinaryUtils.h"
13
#include "llvm/ADT/StringRef.h"
14
#include "llvm/ADT/StringSwitch.h"
15
#include "llvm/ADT/Triple.h"
16
#include "llvm/Support/Endian.h"
17
#include "llvm/Support/ErrorHandling.h"
18
19
using namespace llvm::MachO;
20
using namespace lld::mach_o::normalized;
21
22
namespace lld {
23
namespace mach_o {
24
25
using llvm::support::ulittle32_t;
26
using llvm::support::little32_t;
27
28
29
class ArchHandler_arm : public ArchHandler {
30
public:
31
33
  ArchHandler_arm() = default;
32
33
  ~ArchHandler_arm() override = default;
33
34
18
  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
35
36
217
  Reference::KindArch kindArch() override { return Reference::KindArch::ARM; }
37
38
  const ArchHandler::StubInfo &stubInfo() override;
39
  bool isCallSite(const Reference &) override;
40
  bool isPointer(const Reference &) override;
41
  bool isPairedReloc(const normalized::Relocation &) override;
42
  bool isNonCallBranch(const Reference &) override;
43
44
6
  bool needsCompactUnwind() override {
45
6
    return false;
46
6
  }
47
0
  Reference::KindValue imageOffsetKind() override {
48
0
    return invalid;
49
0
  }
50
0
  Reference::KindValue imageOffsetKindIndirect() override {
51
0
    return invalid;
52
0
  }
53
54
0
  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
55
0
    return invalid;
56
0
  }
57
58
0
  Reference::KindValue unwindRefToCIEKind() override {
59
0
    return invalid;
60
0
  }
61
62
0
  Reference::KindValue unwindRefToFunctionKind() override {
63
0
    return invalid;
64
0
  }
65
66
0
  Reference::KindValue unwindRefToEhFrameKind() override {
67
0
    return invalid;
68
0
  }
69
70
2
  Reference::KindValue lazyImmediateLocationKind() override {
71
2
    return lazyImmediateLocation;
72
2
  }
73
74
0
  Reference::KindValue pointerKind() override {
75
0
    return invalid;
76
0
  }
77
78
0
  uint32_t dwarfCompactUnwindType() override {
79
0
    // FIXME
80
0
    return -1;
81
0
  }
82
83
  llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
84
                               const DefinedAtom *inAtom,
85
                               uint32_t offsetInAtom,
86
                               uint64_t fixupAddress, bool swap,
87
                               FindAtomBySectionAndAddress atomFromAddress,
88
                               FindAtomBySymbolIndex atomFromSymbolIndex,
89
                               Reference::KindValue *kind,
90
                               const lld::Atom **target,
91
                               Reference::Addend *addend) override;
92
  llvm::Error
93
      getPairReferenceInfo(const normalized::Relocation &reloc1,
94
                           const normalized::Relocation &reloc2,
95
                           const DefinedAtom *inAtom,
96
                           uint32_t offsetInAtom,
97
                           uint64_t fixupAddress, bool swap, bool scatterable,
98
                           FindAtomBySectionAndAddress atomFromAddress,
99
                           FindAtomBySymbolIndex atomFromSymbolIndex,
100
                           Reference::KindValue *kind,
101
                           const lld::Atom **target,
102
                           Reference::Addend *addend) override;
103
104
  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
105
                           FindAddressForAtom findAddress,
106
                           FindAddressForAtom findSectionAddress,
107
                           uint64_t imageBaseAddress,
108
                           llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
109
110
  void appendSectionRelocations(const DefinedAtom &atom,
111
                                uint64_t atomSectionOffset,
112
                                const Reference &ref,
113
                                FindSymbolIndexForAtom,
114
                                FindSectionIndexForAtom,
115
                                FindAddressForAtom,
116
                                normalized::Relocations &) override;
117
118
  void addAdditionalReferences(MachODefinedAtom &atom) override;
119
120
243
  bool isDataInCodeTransition(Reference::KindValue refKind) override {
121
243
    switch (refKind) {
122
52
    case modeThumbCode:
123
52
    case modeArmCode:
124
52
    case modeData:
125
52
      return true;
126
191
    default:
127
191
      return false;
128
0
      break;
129
0
    }
130
0
  }
131
132
  Reference::KindValue dataInCodeTransitionStart(
133
24
                                        const MachODefinedAtom &atom) override {
134
24
    return modeData;
135
24
  }
136
137
  Reference::KindValue dataInCodeTransitionEnd(
138
6
                                        const MachODefinedAtom &atom) override {
139
6
    return atom.isThumb() ? 
modeThumbCode3
:
modeArmCode3
;
140
6
  }
141
142
  bool isThumbFunction(const DefinedAtom &atom) override;
143
  const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
144
                                const DefinedAtom &) override;
145
146
private:
147
  friend class Thumb2ToArmShimAtom;
148
  friend class ArmToThumbShimAtom;
149
150
  static const Registry::KindStrings _sKindStrings[];
151
  static const StubInfo              _sStubInfoArmPIC;
152
153
  enum ArmKind : Reference::KindValue {
154
    invalid,               /// for error condition
155
156
    modeThumbCode,         /// Content starting at this offset is thumb.
157
    modeArmCode,           /// Content starting at this offset is arm.
158
    modeData,              /// Content starting at this offset is data.
159
160
    // Kinds found in mach-o .o files:
161
    thumb_bl22,            /// ex: bl _foo
162
    thumb_b22,             /// ex: b _foo
163
    thumb_movw,            /// ex: movw r1, :lower16:_foo
164
    thumb_movt,            /// ex: movt r1, :lower16:_foo
165
    thumb_movw_funcRel,    /// ex: movw r1, :lower16:(_foo-(L1+4))
166
    thumb_movt_funcRel,    /// ex: movt r1, :upper16:(_foo-(L1+4))
167
    arm_bl24,              /// ex: bl _foo
168
    arm_b24,               /// ex: b _foo
169
    arm_movw,              /// ex: movw r1, :lower16:_foo
170
    arm_movt,              /// ex: movt r1, :lower16:_foo
171
    arm_movw_funcRel,      /// ex: movw r1, :lower16:(_foo-(L1+4))
172
    arm_movt_funcRel,      /// ex: movt r1, :upper16:(_foo-(L1+4))
173
    pointer32,             /// ex: .long _foo
174
    delta32,               /// ex: .long _foo - .
175
176
    // Kinds introduced by Passes:
177
    lazyPointer,           /// Location contains a lazy pointer.
178
    lazyImmediateLocation, /// Location contains immediate value used in stub.
179
  };
180
181
  // Utility functions for inspecting/updating instructions.
182
  static bool isThumbMovw(uint32_t instruction);
183
  static bool isThumbMovt(uint32_t instruction);
184
  static bool isArmMovw(uint32_t instruction);
185
  static bool isArmMovt(uint32_t instruction);
186
  static int32_t getDisplacementFromThumbBranch(uint32_t instruction, uint32_t);
187
  static int32_t getDisplacementFromArmBranch(uint32_t instruction);
188
  static uint16_t getWordFromThumbMov(uint32_t instruction);
189
  static uint16_t getWordFromArmMov(uint32_t instruction);
190
  static uint32_t clearThumbBit(uint32_t value, const Atom *target);
191
  static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp,
192
                                             bool targetIsThumb);
193
  static uint32_t setDisplacementInThumbBranch(uint32_t instr, uint32_t ia,
194
                                               int32_t disp, bool targetThumb);
195
  static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word);
196
  static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word);
197
198
  StringRef stubName(const DefinedAtom &);
199
  bool useExternalRelocationTo(const Atom &target);
200
201
  void applyFixupFinal(const Reference &ref, uint8_t *location,
202
                       uint64_t fixupAddress, uint64_t targetAddress,
203
                       uint64_t inAtomAddress, bool &thumbMode,
204
                       bool targetIsThumb);
205
206
  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
207
                             uint64_t fixupAddress,
208
                             uint64_t targetAddress,
209
                             uint64_t inAtomAddress, bool &thumbMode,
210
                             bool targetIsThumb);
211
};
212
213
//===----------------------------------------------------------------------===//
214
//  ArchHandler_arm
215
//===----------------------------------------------------------------------===//
216
217
const Registry::KindStrings ArchHandler_arm::_sKindStrings[] = {
218
  LLD_KIND_STRING_ENTRY(invalid),
219
  LLD_KIND_STRING_ENTRY(modeThumbCode),
220
  LLD_KIND_STRING_ENTRY(modeArmCode),
221
  LLD_KIND_STRING_ENTRY(modeData),
222
  LLD_KIND_STRING_ENTRY(thumb_bl22),
223
  LLD_KIND_STRING_ENTRY(thumb_b22),
224
  LLD_KIND_STRING_ENTRY(thumb_movw),
225
  LLD_KIND_STRING_ENTRY(thumb_movt),
226
  LLD_KIND_STRING_ENTRY(thumb_movw_funcRel),
227
  LLD_KIND_STRING_ENTRY(thumb_movt_funcRel),
228
  LLD_KIND_STRING_ENTRY(arm_bl24),
229
  LLD_KIND_STRING_ENTRY(arm_b24),
230
  LLD_KIND_STRING_ENTRY(arm_movw),
231
  LLD_KIND_STRING_ENTRY(arm_movt),
232
  LLD_KIND_STRING_ENTRY(arm_movw_funcRel),
233
  LLD_KIND_STRING_ENTRY(arm_movt_funcRel),
234
  LLD_KIND_STRING_ENTRY(pointer32),
235
  LLD_KIND_STRING_ENTRY(delta32),
236
  LLD_KIND_STRING_ENTRY(lazyPointer),
237
  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
238
  LLD_KIND_STRING_END
239
};
240
241
const ArchHandler::StubInfo ArchHandler_arm::_sStubInfoArmPIC = {
242
  "dyld_stub_binder",
243
244
  // References in lazy pointer
245
  { Reference::KindArch::ARM, pointer32, 0, 0 },
246
  { Reference::KindArch::ARM, lazyPointer, 0, 0 },
247
248
  // GOT pointer to dyld_stub_binder
249
  { Reference::KindArch::ARM, pointer32, 0, 0 },
250
251
  // arm code alignment 2^2
252
  2,
253
254
  // Stub size and code
255
  16,
256
  { 0x04, 0xC0, 0x9F, 0xE5,       //  ldr ip, pc + 12
257
    0x0C, 0xC0, 0x8F, 0xE0,       //  add ip, pc, ip
258
    0x00, 0xF0, 0x9C, 0xE5,       //  ldr pc, [ip]
259
    0x00, 0x00, 0x00, 0x00 },     //  .long L_foo$lazy_ptr - (L1$scv + 8)
260
  { Reference::KindArch::ARM, delta32, 12, 0 },
261
  { false, 0, 0, 0 },
262
263
  // Stub Helper size and code
264
  12,
265
  { 0x00, 0xC0, 0x9F, 0xE5,       // ldr   ip, [pc, #0]
266
    0x00, 0x00, 0x00, 0xEA,       // b       _helperhelper
267
    0x00, 0x00, 0x00, 0x00 },     // .long  lazy-info-offset
268
  { Reference::KindArch::ARM, lazyImmediateLocation, 8, 0 },
269
  { Reference::KindArch::ARM, arm_b24, 4, 0 },
270
271
  // Stub helper image cache content type
272
  DefinedAtom::typeGOT,
273
274
  // Stub Helper-Common size and code
275
  36,
276
  // Stub helper alignment
277
  2,
278
  { // push lazy-info-offset
279
    0x04, 0xC0, 0x2D, 0xE5,       // str ip, [sp, #-4]!
280
    // push address of dyld_mageLoaderCache
281
    0x10, 0xC0, 0x9F, 0xE5,       // ldr  ip, L1
282
    0x0C, 0xC0, 0x8F, 0xE0,       // add  ip, pc, ip
283
    0x04, 0xC0, 0x2D, 0xE5,       // str ip, [sp, #-4]!
284
    // jump through dyld_stub_binder
285
    0x08, 0xC0, 0x9F, 0xE5,       // ldr  ip, L2
286
    0x0C, 0xC0, 0x8F, 0xE0,       // add  ip, pc, ip
287
    0x00, 0xF0, 0x9C, 0xE5,       // ldr  pc, [ip]
288
    0x00, 0x00, 0x00, 0x00,       // L1: .long fFastStubGOTAtom - (helper+16)
289
    0x00, 0x00, 0x00, 0x00 },     // L2: .long dyld_stub_binder - (helper+28)
290
  { Reference::KindArch::ARM, delta32, 28, 0xC },
291
  { false, 0, 0, 0 },
292
  { Reference::KindArch::ARM, delta32, 32, 0x04 },
293
  { false, 0, 0, 0 }
294
};
295
296
106
const ArchHandler::StubInfo &ArchHandler_arm::stubInfo() {
297
106
  // If multiple kinds of stubs are supported, select which StubInfo here.
298
106
  return _sStubInfoArmPIC;
299
106
}
300
301
64
bool ArchHandler_arm::isCallSite(const Reference &ref) {
302
64
  switch (ref.kindValue()) {
303
22
  case thumb_b22:
304
22
  case thumb_bl22:
305
22
  case arm_b24:
306
22
  case arm_bl24:
307
22
    return true;
308
42
  default:
309
42
    return false;
310
0
  }
311
0
}
312
313
88
bool ArchHandler_arm::isPointer(const Reference &ref) {
314
88
  return (ref.kindValue() == pointer32);
315
88
}
316
317
82
bool ArchHandler_arm::isNonCallBranch(const Reference &ref) {
318
82
  switch (ref.kindValue()) {
319
6
  case thumb_b22:
320
6
  case arm_b24:
321
6
    return true;
322
76
  default:
323
76
    return false;
324
0
  }
325
0
}
326
327
169
bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) {
328
169
  switch (reloc.type) {
329
99
  case ARM_RELOC_SECTDIFF:
330
99
  case ARM_RELOC_LOCAL_SECTDIFF:
331
99
  case ARM_RELOC_HALF_SECTDIFF:
332
99
  case ARM_RELOC_HALF:
333
99
    return true;
334
70
  default:
335
70
    return false;
336
0
  }
337
0
}
338
339
/// Trace references from stub atom to lazy pointer to target and get its name.
340
0
StringRef ArchHandler_arm::stubName(const DefinedAtom &stubAtom) {
341
0
  assert(stubAtom.contentType() == DefinedAtom::typeStub);
342
0
  for (const Reference *ref : stubAtom) {
343
0
    if (const DefinedAtom* 
lp0
= dyn_cast<DefinedAtom>(ref->target())) {
344
0
      if (lp->contentType() != DefinedAtom::typeLazyPointer)
345
0
        continue;
346
0
      
for (const Reference *ref2 : *lp) 0
{
347
0
        if (ref2->kindValue() != lazyPointer)
348
0
          continue;
349
0
        return ref2->target()->name();
350
0
      }
351
0
    }
352
0
  }
353
0
  return "stub";
354
0
}
355
356
/// Extract displacement from an ARM b/bl/blx instruction.
357
23
int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
358
23
  // Sign-extend imm24
359
23
  int32_t displacement = (instruction & 0x00FFFFFF) << 2;
360
23
  if ((displacement & 0x02000000) != 0)
361
17
    displacement |= 0xFC000000;
362
23
  // If this is BLX and H bit set, add 2.
363
23
  if ((instruction & 0xFF000000) == 0xFB000000)
364
0
    displacement += 2;
365
23
  return displacement;
366
23
}
367
368
/// Update an ARM b/bl/blx instruction, switching bl <-> blx as needed.
369
uint32_t ArchHandler_arm::setDisplacementInArmBranch(uint32_t instruction,
370
                                                     int32_t displacement,
371
25
                                                     bool targetIsThumb) {
372
25
  assert((displacement <= 33554428) && (displacement > (-33554432))
373
25
                                              && "arm branch out of range");
374
25
  bool is_blx = ((instruction & 0xF0000000) == 0xF0000000);
375
25
  uint32_t newInstruction = (instruction & 0xFF000000);
376
25
  uint32_t h = 0;
377
25
  if (
targetIsThumb25
) {
378
6
    // Force use of BLX.
379
6
    newInstruction = 0xFA000000;
380
6
    if (
!is_blx6
) {
381
1
      assert(((instruction & 0xF0000000) == 0xE0000000)
382
1
                                                   && "no conditional arm blx");
383
1
      assert(((instruction & 0xFF000000) == 0xEB000000)
384
1
                                             && "no arm pc-rel BX instruction");
385
1
    }
386
6
    if (displacement & 2)
387
0
      h = 1;
388
6
  }
389
19
  else {
390
19
    // Force use of B/BL.
391
19
    if (is_blx)
392
1
      newInstruction = 0xEB000000;
393
19
  }
394
25
  newInstruction |= (h << 24) | ((displacement >> 2) & 0x00FFFFFF);
395
25
  return newInstruction;
396
25
}
397
398
/// Extract displacement from a thumb b/bl/blx instruction.
399
int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction,
400
31
                                                        uint32_t instrAddr) {
401
31
  bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
402
31
  uint32_t s = (instruction >> 10) & 0x1;
403
31
  uint32_t j1 = (instruction >> 29) & 0x1;
404
31
  uint32_t j2 = (instruction >> 27) & 0x1;
405
31
  uint32_t imm10 = instruction & 0x3FF;
406
31
  uint32_t imm11 = (instruction >> 16) & 0x7FF;
407
31
  uint32_t i1 = (j1 == s);
408
31
  uint32_t i2 = (j2 == s);
409
31
  uint32_t dis =
410
31
      (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
411
31
  int32_t sdis = dis;
412
31
  int32_t result = s ? 
(sdis | 0xFE000000)18
:
sdis13
;
413
31
  if (
is_blx && 31
(instrAddr & 0x2)11
) {
414
5
    // The thumb blx instruction always has low bit of imm11 as zero.  The way
415
5
    // a 2-byte aligned blx can branch to a 4-byte aligned ARM target is that
416
5
    // the blx instruction always 4-byte aligns the pc before adding the
417
5
    // displacement from the blx.  We must emulate that when decoding this.
418
5
    result -= 2;
419
5
  }
420
31
  return result;
421
31
}
422
423
/// Update a thumb b/bl/blx instruction, switching bl <-> blx as needed.
424
uint32_t ArchHandler_arm::setDisplacementInThumbBranch(uint32_t instruction,
425
                                                       uint32_t instrAddr,
426
                                                       int32_t displacement,
427
31
                                                       bool targetIsThumb) {
428
31
  assert((displacement <= 16777214) && (displacement > (-16777216))
429
31
                                              && "thumb branch out of range");
430
31
  bool is_bl = ((instruction & 0xD000F800) == 0xD000F000);
431
31
  bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
432
31
  bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
433
31
  uint32_t newInstruction = (instruction & 0xD000F800);
434
31
  if (
is_bl || 31
is_blx15
) {
435
27
    if (
targetIsThumb27
) {
436
14
      newInstruction = 0xD000F000; // Use bl
437
27
    } else {
438
13
      newInstruction = 0xC000F000; // Use blx
439
13
      // See note in getDisplacementFromThumbBranch() about blx.
440
13
      if (instrAddr & 0x2)
441
4
        displacement += 2;
442
13
    }
443
31
  } else 
if (4
is_b4
) {
444
4
    assert(targetIsThumb && "no pc-rel thumb branch instruction that "
445
4
                             "switches to arm mode");
446
4
  }
447
0
  else {
448
0
    llvm_unreachable("thumb branch22 reloc on a non-branch instruction");
449
4
  }
450
31
  uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
451
31
  uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
452
31
  uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
453
31
  uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF;
454
31
  uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF;
455
31
  uint32_t j1 = (i1 == s);
456
31
  uint32_t j2 = (i2 == s);
457
31
  uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11;
458
31
  uint32_t firstDisp = (s << 10) | imm10;
459
31
  newInstruction |= (nextDisp << 16) | firstDisp;
460
31
  return newInstruction;
461
31
}
462
463
25
bool ArchHandler_arm::isThumbMovw(uint32_t instruction) {
464
25
  return (instruction & 0x8000FBF0) == 0x0000F240;
465
25
}
466
467
25
bool ArchHandler_arm::isThumbMovt(uint32_t instruction) {
468
25
  return (instruction & 0x8000FBF0) == 0x0000F2C0;
469
25
}
470
471
20
bool ArchHandler_arm::isArmMovw(uint32_t instruction) {
472
20
  return (instruction & 0x0FF00000) == 0x03000000;
473
20
}
474
475
20
bool ArchHandler_arm::isArmMovt(uint32_t instruction) {
476
20
  return (instruction & 0x0FF00000) == 0x03400000;
477
20
}
478
479
50
uint16_t ArchHandler_arm::getWordFromThumbMov(uint32_t instruction) {
480
50
  assert(isThumbMovw(instruction) || isThumbMovt(instruction));
481
50
  uint32_t i = ((instruction & 0x00000400) >> 10);
482
50
  uint32_t imm4 = (instruction & 0x0000000F);
483
50
  uint32_t imm3 = ((instruction & 0x70000000) >> 28);
484
50
  uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
485
50
  return (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
486
50
}
487
488
40
uint16_t ArchHandler_arm::getWordFromArmMov(uint32_t instruction) {
489
40
  assert(isArmMovw(instruction) || isArmMovt(instruction));
490
40
  uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
491
40
  uint32_t imm12 = (instruction & 0x00000FFF);
492
40
  return (imm4 << 12) | imm12;
493
40
}
494
495
50
uint32_t ArchHandler_arm::setWordFromThumbMov(uint32_t instr, uint16_t word) {
496
50
  assert(isThumbMovw(instr) || isThumbMovt(instr));
497
50
  uint32_t imm4 = (word & 0xF000) >> 12;
498
50
  uint32_t i =    (word & 0x0800) >> 11;
499
50
  uint32_t imm3 = (word & 0x0700) >> 8;
500
50
  uint32_t imm8 =  word & 0x00FF;
501
50
  return (instr & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
502
50
}
503
504
40
uint32_t ArchHandler_arm::setWordFromArmMov(uint32_t instr, uint16_t word) {
505
40
  assert(isArmMovw(instr) || isArmMovt(instr));
506
40
  uint32_t imm4 = (word & 0xF000) >> 12;
507
40
  uint32_t imm12 = word & 0x0FFF;
508
40
  return (instr & 0xFFF0F000) | (imm4 << 16) | imm12;
509
40
}
510
511
57
uint32_t ArchHandler_arm::clearThumbBit(uint32_t value, const Atom *target) {
512
57
  // The assembler often adds one to the address of a thumb function.
513
57
  // We need to undo that so it does not look like an addend.
514
57
  if (
value & 157
) {
515
8
    if (
isa<DefinedAtom>(target)8
) {
516
8
      const MachODefinedAtom *machoTarget =
517
8
          reinterpret_cast<const MachODefinedAtom *>(target);
518
8
      if (machoTarget->isThumb())
519
8
        value &= -2; // mask off thumb-bit
520
8
    }
521
8
  }
522
57
  return value;
523
57
}
524
525
llvm::Error ArchHandler_arm::getReferenceInfo(
526
    const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
527
    uint64_t fixupAddress, bool isBig,
528
    FindAtomBySectionAndAddress atomFromAddress,
529
    FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
530
70
    const lld::Atom **target, Reference::Addend *addend) {
531
70
  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
532
70
  uint64_t targetAddress;
533
70
  uint32_t instruction = *(const ulittle32_t *)fixupContent;
534
70
  int32_t displacement;
535
70
  switch (relocPattern(reloc)) {
536
14
  case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4:
537
14
    // ex: bl _foo (and _foo is undefined)
538
14
    if ((instruction & 0xD000F800) == 0x9000F000)
539
4
      *kind = thumb_b22;
540
14
    else
541
10
      *kind = thumb_bl22;
542
14
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
543
0
      return ec;
544
14
    // Instruction contains branch to addend.
545
14
    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
546
14
    *addend = fixupAddress + 4 + displacement;
547
14
    return llvm::Error::success();
548
15
  case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
549
15
    // ex: bl _foo (and _foo is defined)
550
15
    if ((instruction & 0xD000F800) == 0x9000F000)
551
0
      *kind = thumb_b22;
552
15
    else
553
15
      *kind = thumb_bl22;
554
15
    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
555
15
    targetAddress = fixupAddress + 4 + displacement;
556
15
    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
557
2
  case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4:
558
2
    // ex: bl _foo+4 (and _foo is defined)
559
2
    if ((instruction & 0xD000F800) == 0x9000F000)
560
0
      *kind = thumb_b22;
561
2
    else
562
2
      *kind = thumb_bl22;
563
2
    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
564
2
    targetAddress = fixupAddress + 4 + displacement;
565
2
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
566
0
      return ec;
567
2
    // reloc.value is target atom's address.  Instruction contains branch
568
2
    // to atom+addend.
569
2
    *addend += (targetAddress - reloc.value);
570
2
    return llvm::Error::success();
571
13
  case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
572
13
    // ex: bl _foo (and _foo is undefined)
573
13
    if (((instruction & 0x0F000000) == 0x0A000000)
574
7
        && ((instruction & 0xF0000000) != 0xF0000000))
575
4
      *kind = arm_b24;
576
13
    else
577
9
      *kind = arm_bl24;
578
13
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
579
0
      return ec;
580
13
    // Instruction contains branch to addend.
581
13
    displacement = getDisplacementFromArmBranch(instruction);
582
13
    *addend = fixupAddress + 8 + displacement;
583
13
    return llvm::Error::success();
584
8
  case ARM_RELOC_BR24 | rPcRel | rLength4:
585
8
    // ex: bl _foo (and _foo is defined)
586
8
    if (((instruction & 0x0F000000) == 0x0A000000)
587
3
        && ((instruction & 0xF0000000) != 0xF0000000))
588
0
      *kind = arm_b24;
589
8
    else
590
8
      *kind = arm_bl24;
591
8
    displacement = getDisplacementFromArmBranch(instruction);
592
8
    targetAddress = fixupAddress + 8 + displacement;
593
8
    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
594
2
  case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4:
595
2
    // ex: bl _foo+4 (and _foo is defined)
596
2
    if (((instruction & 0x0F000000) == 0x0A000000)
597
0
        && ((instruction & 0xF0000000) != 0xF0000000))
598
0
      *kind = arm_b24;
599
2
    else
600
2
      *kind = arm_bl24;
601
2
    displacement = getDisplacementFromArmBranch(instruction);
602
2
    targetAddress = fixupAddress + 8 + displacement;
603
2
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
604
0
      return ec;
605
2
    // reloc.value is target atom's address.  Instruction contains branch
606
2
    // to atom+addend.
607
2
    *addend += (targetAddress - reloc.value);
608
2
    return llvm::Error::success();
609
6
  case ARM_RELOC_VANILLA | rExtern | rLength4:
610
6
    // ex: .long _foo (and _foo is undefined)
611
6
    *kind = pointer32;
612
6
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
613
0
      return ec;
614
6
    *addend = instruction;
615
6
    return llvm::Error::success();
616
8
  case ARM_RELOC_VANILLA | rLength4:
617
8
    // ex: .long _foo (and _foo is defined)
618
8
    *kind = pointer32;
619
8
    if (auto ec = atomFromAddress(reloc.symbol, instruction, target, addend))
620
0
      return ec;
621
8
    *addend = clearThumbBit((uint32_t) * addend, *target);
622
8
    return llvm::Error::success();
623
2
  case ARM_RELOC_VANILLA | rScattered | rLength4:
624
2
    // ex: .long _foo+a (and _foo is defined)
625
2
    *kind = pointer32;
626
2
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
627
0
      return ec;
628
2
    *addend += (clearThumbBit(instruction, *target) - reloc.value);
629
2
    return llvm::Error::success();
630
0
  default:
631
0
    return llvm::make_error<GenericError>("unsupported arm relocation type");
632
0
  }
633
0
  return llvm::Error::success();
634
0
}
635
636
llvm::Error
637
ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
638
                                     const normalized::Relocation &reloc2,
639
                                     const DefinedAtom *inAtom,
640
                                     uint32_t offsetInAtom,
641
                                     uint64_t fixupAddress, bool isBig,
642
                                     bool scatterable,
643
                                     FindAtomBySectionAndAddress atomFromAddr,
644
                                     FindAtomBySymbolIndex atomFromSymbolIndex,
645
                                     Reference::KindValue *kind,
646
                                     const lld::Atom **target,
647
99
                                     Reference::Addend *addend) {
648
99
  bool pointerDiff = false;
649
99
  bool funcRel;
650
99
  bool top;
651
99
  bool thumbReloc;
652
99
  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
653
11
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenThmbLo) << 16 |
654
11
         ARM_RELOC_PAIR           | rScattered | rLenThmbLo):
655
11
    // ex: movw r1, :lower16:(_x-L1) [thumb mode]
656
11
    *kind = thumb_movw_funcRel;
657
11
    funcRel = true;
658
11
    top = false;
659
11
    thumbReloc = true;
660
11
    break;
661
11
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenThmbHi) << 16 |
662
11
         ARM_RELOC_PAIR           | rScattered | rLenThmbHi):
663
11
    // ex: movt r1, :upper16:(_x-L1) [thumb mode]
664
11
    *kind = thumb_movt_funcRel;
665
11
    funcRel = true;
666
11
    top = true;
667
11
    thumbReloc = true;
668
11
    break;
669
8
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenArmLo) << 16 |
670
8
         ARM_RELOC_PAIR           | rScattered | rLenArmLo):
671
8
    // ex: movw r1, :lower16:(_x-L1) [arm mode]
672
8
    *kind = arm_movw_funcRel;
673
8
    funcRel = true;
674
8
    top = false;
675
8
    thumbReloc = false;
676
8
    break;
677
8
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenArmHi) << 16 |
678
8
         ARM_RELOC_PAIR           | rScattered | rLenArmHi):
679
8
    // ex: movt r1, :upper16:(_x-L1) [arm mode]
680
8
    *kind = arm_movt_funcRel;
681
8
    funcRel = true;
682
8
    top = true;
683
8
    thumbReloc = false;
684
8
    break;
685
8
  case ((ARM_RELOC_HALF     | rLenThmbLo) << 16 |
686
8
         ARM_RELOC_PAIR     | rLenThmbLo):
687
8
    // ex: movw r1, :lower16:_x [thumb mode]
688
8
    *kind = thumb_movw;
689
8
    funcRel = false;
690
8
    top = false;
691
8
    thumbReloc = true;
692
8
    break;
693
8
  case ((ARM_RELOC_HALF     | rLenThmbHi) << 16 |
694
8
         ARM_RELOC_PAIR     | rLenThmbHi):
695
8
    // ex: movt r1, :upper16:_x [thumb mode]
696
8
    *kind = thumb_movt;
697
8
    funcRel = false;
698
8
    top = true;
699
8
    thumbReloc = true;
700
8
    break;
701
6
  case ((ARM_RELOC_HALF     | rLenArmLo) << 16 |
702
6
         ARM_RELOC_PAIR     | rLenArmLo):
703
6
    // ex: movw r1, :lower16:_x [arm mode]
704
6
    *kind = arm_movw;
705
6
    funcRel = false;
706
6
    top = false;
707
6
    thumbReloc = false;
708
6
    break;
709
6
  case ((ARM_RELOC_HALF     | rLenArmHi) << 16 |
710
6
         ARM_RELOC_PAIR     | rLenArmHi):
711
6
    // ex: movt r1, :upper16:_x [arm mode]
712
6
    *kind = arm_movt;
713
6
    funcRel = false;
714
6
    top = true;
715
6
    thumbReloc = false;
716
6
    break;
717
2
  case ((ARM_RELOC_HALF | rScattered  | rLenThmbLo) << 16 |
718
2
         ARM_RELOC_PAIR               | rLenThmbLo):
719
2
    // ex: movw r1, :lower16:_x+a [thumb mode]
720
2
    *kind = thumb_movw;
721
2
    funcRel = false;
722
2
    top = false;
723
2
    thumbReloc = true;
724
2
    break;
725
2
  case ((ARM_RELOC_HALF | rScattered  | rLenThmbHi) << 16 |
726
2
         ARM_RELOC_PAIR               | rLenThmbHi):
727
2
    // ex: movt r1, :upper16:_x+a [thumb mode]
728
2
    *kind = thumb_movt;
729
2
    funcRel = false;
730
2
    top = true;
731
2
    thumbReloc = true;
732
2
    break;
733
2
  case ((ARM_RELOC_HALF | rScattered  | rLenArmLo) << 16 |
734
2
         ARM_RELOC_PAIR               | rLenArmLo):
735
2
    // ex: movw r1, :lower16:_x+a [arm mode]
736
2
    *kind = arm_movw;
737
2
    funcRel = false;
738
2
    top = false;
739
2
    thumbReloc = false;
740
2
    break;
741
2
  case ((ARM_RELOC_HALF | rScattered  | rLenArmHi) << 16 |
742
2
         ARM_RELOC_PAIR               | rLenArmHi):
743
2
    // ex: movt r1, :upper16:_x+a [arm mode]
744
2
    *kind = arm_movt;
745
2
    funcRel = false;
746
2
    top = true;
747
2
    thumbReloc = false;
748
2
    break;
749
4
  case ((ARM_RELOC_HALF | rExtern   | rLenThmbLo) << 16 |
750
4
         ARM_RELOC_PAIR             | rLenThmbLo):
751
4
    // ex: movw r1, :lower16:_undef [thumb mode]
752
4
    *kind = thumb_movw;
753
4
    funcRel = false;
754
4
    top = false;
755
4
    thumbReloc = true;
756
4
    break;
757
4
  case ((ARM_RELOC_HALF | rExtern   | rLenThmbHi) << 16 |
758
4
         ARM_RELOC_PAIR             | rLenThmbHi):
759
4
    // ex: movt r1, :upper16:_undef [thumb mode]
760
4
    *kind = thumb_movt;
761
4
    funcRel = false;
762
4
    top = true;
763
4
    thumbReloc = true;
764
4
    break;
765
4
  case ((ARM_RELOC_HALF | rExtern   | rLenArmLo) << 16 |
766
4
         ARM_RELOC_PAIR             | rLenArmLo):
767
4
    // ex: movw r1, :lower16:_undef [arm mode]
768
4
    *kind = arm_movw;
769
4
    funcRel = false;
770
4
    top = false;
771
4
    thumbReloc = false;
772
4
    break;
773
4
  case ((ARM_RELOC_HALF | rExtern   | rLenArmHi) << 16 |
774
4
         ARM_RELOC_PAIR             | rLenArmHi):
775
4
    // ex: movt r1, :upper16:_undef [arm mode]
776
4
    *kind = arm_movt;
777
4
    funcRel = false;
778
4
    top = true;
779
4
    thumbReloc = false;
780
4
    break;
781
9
  case ((ARM_RELOC_SECTDIFF       | rScattered | rLength4) << 16 |
782
9
         ARM_RELOC_PAIR           | rScattered | rLength4):
783
9
  case ((ARM_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
784
9
         ARM_RELOC_PAIR           | rScattered | rLength4):
785
9
    // ex: .long _foo - .
786
9
    pointerDiff = true;
787
9
    break;
788
0
  default:
789
0
    return llvm::make_error<GenericError>("unsupported arm relocation pair");
790
99
  }
791
99
  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
792
99
  uint32_t instruction = *(const ulittle32_t *)fixupContent;
793
99
  uint32_t value;
794
99
  uint32_t fromAddress;
795
99
  uint32_t toAddress;
796
99
  uint16_t instruction16;
797
99
  uint16_t other16;
798
99
  const lld::Atom *fromTarget;
799
99
  Reference::Addend offsetInTo;
800
99
  Reference::Addend offsetInFrom;
801
99
  if (
pointerDiff99
) {
802
9
    toAddress = reloc1.value;
803
9
    fromAddress = reloc2.value;
804
9
    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
805
0
      return ec;
806
9
    
if (auto 9
ec9
= atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
807
0
      return ec;
808
9
    
if (9
scatterable && 9
(fromTarget != inAtom)9
)
809
0
      return llvm::make_error<GenericError>(
810
0
          "SECTDIFF relocation where subtrahend label is not in atom");
811
9
    *kind = delta32;
812
9
    value = clearThumbBit(instruction, *target);
813
9
    *addend = (int32_t)(value - (toAddress - fixupAddress));
814
99
  } else 
if (90
funcRel90
) {
815
38
    toAddress = reloc1.value;
816
38
    fromAddress = reloc2.value;
817
38
    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
818
0
      return ec;
819
38
    
if (auto 38
ec38
= atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
820
0
      return ec;
821
38
    
if (38
fromTarget != inAtom38
)
822
0
      return llvm::make_error<GenericError>("ARM_RELOC_HALF_SECTDIFF relocation"
823
0
                                     " where subtrahend label is not in atom");
824
38
    other16 = (reloc2.offset & 0xFFFF);
825
38
    if (
thumbReloc38
) {
826
22
      if (
top22
) {
827
11
        if (!isThumbMovt(instruction))
828
0
          return llvm::make_error<GenericError>("expected movt instruction");
829
22
      }
830
11
      else {
831
11
        if (!isThumbMovw(instruction))
832
0
          return llvm::make_error<GenericError>("expected movw instruction");
833
22
      }
834
22
      instruction16 = getWordFromThumbMov(instruction);
835
22
    }
836
16
    else {
837
16
      if (
top16
) {
838
8
        if (!isArmMovt(instruction))
839
0
          return llvm::make_error<GenericError>("expected movt instruction");
840
16
      }
841
8
      else {
842
8
        if (!isArmMovw(instruction))
843
0
          return llvm::make_error<GenericError>("expected movw instruction");
844
16
      }
845
16
      instruction16 = getWordFromArmMov(instruction);
846
16
    }
847
38
    
if (38
top38
)
848
19
      value = (instruction16 << 16) | other16;
849
38
    else
850
19
      value = (other16 << 16) | instruction16;
851
38
    value = clearThumbBit(value, *target);
852
38
    int64_t ta = (int64_t) value - (toAddress - fromAddress);
853
38
    *addend = ta - offsetInFrom;
854
38
    return llvm::Error::success();
855
52
  } else {
856
52
    uint32_t sectIndex;
857
52
    if (
thumbReloc52
) {
858
28
      if (
top28
) {
859
14
        if (!isThumbMovt(instruction))
860
0
          return llvm::make_error<GenericError>("expected movt instruction");
861
28
      }
862
14
      else {
863
14
        if (!isThumbMovw(instruction))
864
0
          return llvm::make_error<GenericError>("expected movw instruction");
865
28
      }
866
28
      instruction16 = getWordFromThumbMov(instruction);
867
28
    }
868
24
    else {
869
24
      if (
top24
) {
870
12
        if (!isArmMovt(instruction))
871
0
          return llvm::make_error<GenericError>("expected movt instruction");
872
24
      }
873
12
      else {
874
12
        if (!isArmMovw(instruction))
875
0
          return llvm::make_error<GenericError>("expected movw instruction");
876
24
      }
877
24
      instruction16 = getWordFromArmMov(instruction);
878
24
    }
879
52
    other16 = (reloc2.offset & 0xFFFF);
880
52
    if (top)
881
26
      value = (instruction16 << 16) | other16;
882
52
    else
883
26
      value = (other16 << 16) | instruction16;
884
52
    if (
reloc1.isExtern52
) {
885
16
      if (auto ec = atomFromSymbolIndex(reloc1.symbol, target))
886
0
        return ec;
887
16
      *addend = value;
888
52
    } else {
889
36
      if (
reloc1.scattered36
) {
890
8
        toAddress = reloc1.value;
891
8
        sectIndex = 0;
892
36
      } else {
893
28
        toAddress = value;
894
28
        sectIndex = reloc1.symbol;
895
28
      }
896
36
      if (auto ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo))
897
0
        return ec;
898
36
      *addend = value - toAddress;
899
36
    }
900
90
  }
901
99
902
61
  return llvm::Error::success();
903
99
}
904
905
void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *loc,
906
                                      uint64_t fixupAddress,
907
                                      uint64_t targetAddress,
908
                                      uint64_t inAtomAddress,
909
88
                                      bool &thumbMode, bool targetIsThumb) {
910
88
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
911
0
    return;
912
88
  assert(ref.kindArch() == Reference::KindArch::ARM);
913
88
  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
914
88
  int32_t displacement;
915
88
  uint16_t value16;
916
88
  uint32_t value32;
917
88
  switch (static_cast<ArmKind>(ref.kindValue())) {
918
12
  case modeThumbCode:
919
12
    thumbMode = true;
920
12
    break;
921
1
  case modeArmCode:
922
1
    thumbMode = false;
923
1
    break;
924
8
  case modeData:
925
8
    break;
926
13
  case thumb_b22:
927
13
  case thumb_bl22:
928
13
    assert(thumbMode);
929
13
    displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
930
13
    value32 = setDisplacementInThumbBranch(*loc32, fixupAddress,
931
13
                                           displacement, targetIsThumb);
932
13
    *loc32 = value32;
933
13
    break;
934
2
  case thumb_movw:
935
2
    assert(thumbMode);
936
2
    value16 = (targetAddress + ref.addend()) & 0xFFFF;
937
2
    if (targetIsThumb)
938
1
      value16 |= 1;
939
2
    *loc32 = setWordFromThumbMov(*loc32, value16);
940
2
    break;
941
2
  case thumb_movt:
942
2
    assert(thumbMode);
943
2
    value16 = (targetAddress + ref.addend()) >> 16;
944
2
    *loc32 = setWordFromThumbMov(*loc32, value16);
945
2
    break;
946
3
  case thumb_movw_funcRel:
947
3
    assert(thumbMode);
948
3
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
949
3
    if (targetIsThumb)
950
1
      value16 |= 1;
951
3
    *loc32 = setWordFromThumbMov(*loc32, value16);
952
3
    break;
953
3
  case thumb_movt_funcRel:
954
3
    assert(thumbMode);
955
3
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
956
3
    *loc32 = setWordFromThumbMov(*loc32, value16);
957
3
    break;
958
11
  case arm_b24:
959
11
  case arm_bl24:
960
11
   assert(!thumbMode);
961
11
    displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
962
11
    value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
963
11
    *loc32 = value32;
964
11
    break;
965
2
  case arm_movw:
966
2
    assert(!thumbMode);
967
2
    value16 = (targetAddress + ref.addend()) & 0xFFFF;
968
2
    if (targetIsThumb)
969
1
      value16 |= 1;
970
2
    *loc32 = setWordFromArmMov(*loc32, value16);
971
2
    break;
972
2
  case arm_movt:
973
2
    assert(!thumbMode);
974
2
    value16 = (targetAddress + ref.addend()) >> 16;
975
2
    *loc32 = setWordFromArmMov(*loc32, value16);
976
2
    break;
977
2
  case arm_movw_funcRel:
978
2
    assert(!thumbMode);
979
2
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
980
2
    if (targetIsThumb)
981
1
      value16 |= 1;
982
2
    *loc32 = setWordFromArmMov(*loc32, value16);
983
2
    break;
984
2
  case arm_movt_funcRel:
985
2
    assert(!thumbMode);
986
2
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
987
2
    *loc32 = setWordFromArmMov(*loc32, value16);
988
2
    break;
989
8
  case pointer32:
990
8
    if (targetIsThumb)
991
2
      *loc32 = targetAddress + ref.addend() + 1;
992
8
    else
993
6
      *loc32 = targetAddress + ref.addend();
994
8
    break;
995
11
  case delta32:
996
11
    if (targetIsThumb)
997
2
      *loc32 = targetAddress - fixupAddress + ref.addend() + 1;
998
11
    else
999
9
      *loc32 = targetAddress - fixupAddress + ref.addend();
1000
11
    break;
1001
2
  case lazyPointer:
1002
2
    // do nothing
1003
2
    break;
1004
4
  case lazyImmediateLocation:
1005
4
    *loc32 = ref.addend();
1006
4
    break;
1007
0
  case invalid:
1008
0
    llvm_unreachable("invalid ARM Reference Kind");
1009
0
    break;
1010
88
  }
1011
88
}
1012
1013
void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
1014
                                          bool relocatable,
1015
                                          FindAddressForAtom findAddress,
1016
                                          FindAddressForAtom findSectionAddress,
1017
                                          uint64_t imageBaseAddress,
1018
63
                            llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
1019
63
  // Copy raw bytes.
1020
63
  std::copy(atom.rawContent().begin(), atom.rawContent().end(),
1021
63
            atomContentBuffer.begin());
1022
63
  // Apply fix-ups.
1023
63
  bool thumbMode = false;
1024
245
  for (const Reference *ref : atom) {
1025
245
    uint32_t offset = ref->offsetInAtom();
1026
245
    const Atom *target = ref->target();
1027
245
    uint64_t targetAddress = 0;
1028
245
    bool targetIsThumb = false;
1029
245
    if (const DefinedAtom *
defTarg245
= dyn_cast<DefinedAtom>(target)) {
1030
209
      targetAddress = findAddress(*target);
1031
209
      targetIsThumb = isThumbFunction(*defTarg);
1032
209
    }
1033
245
    uint64_t atomAddress = findAddress(atom);
1034
245
    uint64_t fixupAddress = atomAddress + offset;
1035
245
    if (
relocatable245
) {
1036
157
      applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
1037
157
                            targetAddress, atomAddress, thumbMode,
1038
157
                            targetIsThumb);
1039
245
    } else {
1040
88
      applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
1041
88
                      targetAddress, atomAddress, thumbMode, targetIsThumb);
1042
88
    }
1043
245
  }
1044
63
}
1045
1046
310
bool ArchHandler_arm::useExternalRelocationTo(const Atom &target) {
1047
310
  // Undefined symbols are referenced via external relocations.
1048
310
  if (isa<UndefinedAtom>(&target))
1049
64
    return true;
1050
246
  
if (const DefinedAtom *246
defAtom246
= dyn_cast<DefinedAtom>(&target)) {
1051
246
     switch (defAtom->merge()) {
1052
0
     case DefinedAtom::mergeAsTentative:
1053
0
       // Tentative definitions are referenced via external relocations.
1054
0
       return true;
1055
0
     case DefinedAtom::mergeAsWeak:
1056
0
     case DefinedAtom::mergeAsWeakAndAddressUsed:
1057
0
       // Global weak-defs are referenced via external relocations.
1058
0
       return (defAtom->scope() == DefinedAtom::scopeGlobal);
1059
246
     default:
1060
246
       break;
1061
246
    }
1062
246
  }
1063
246
  // Everything else is reference via an internal relocation.
1064
246
  return false;
1065
246
}
1066
1067
void ArchHandler_arm::applyFixupRelocatable(const Reference &ref, uint8_t *loc,
1068
                                            uint64_t fixupAddress,
1069
                                            uint64_t targetAddress,
1070
                                            uint64_t inAtomAddress,
1071
                                            bool &thumbMode,
1072
157
                                            bool targetIsThumb) {
1073
157
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
1074
2
    return;
1075
157
  assert(ref.kindArch() == Reference::KindArch::ARM);
1076
155
  bool useExternalReloc = useExternalRelocationTo(*ref.target());
1077
155
  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
1078
155
  int32_t displacement;
1079
155
  uint16_t value16;
1080
155
  uint32_t value32;
1081
155
  bool targetIsUndef = isa<UndefinedAtom>(ref.target());
1082
155
  switch (static_cast<ArmKind>(ref.kindValue())) {
1083
13
  case modeThumbCode:
1084
13
    thumbMode = true;
1085
13
    break;
1086
2
  case modeArmCode:
1087
2
    thumbMode = false;
1088
2
    break;
1089
16
  case modeData:
1090
16
    break;
1091
18
  case thumb_b22:
1092
18
  case thumb_bl22:
1093
18
    assert(thumbMode);
1094
18
    if (useExternalReloc)
1095
6
      displacement = (ref.addend() - (fixupAddress + 4));
1096
18
    else
1097
12
      displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
1098
18
    value32 = setDisplacementInThumbBranch(*loc32, fixupAddress,
1099
18
                                           displacement,
1100
12
                                           targetIsUndef || targetIsThumb);
1101
18
    *loc32 = value32;
1102
18
    break;
1103
12
  case thumb_movw:
1104
12
    assert(thumbMode);
1105
12
    if (useExternalReloc)
1106
4
      value16 = ref.addend() & 0xFFFF;
1107
12
    else
1108
8
      value16 = (targetAddress + ref.addend()) & 0xFFFF;
1109
12
    *loc32 = setWordFromThumbMov(*loc32, value16);
1110
12
    break;
1111
12
  case thumb_movt:
1112
12
    assert(thumbMode);
1113
12
    if (useExternalReloc)
1114
4
      value16 = ref.addend() >> 16;
1115
12
    else
1116
8
      value16 = (targetAddress + ref.addend()) >> 16;
1117
12
    *loc32 = setWordFromThumbMov(*loc32, value16);
1118
12
    break;
1119
8
  case thumb_movw_funcRel:
1120
8
    assert(thumbMode);
1121
8
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
1122
8
    *loc32 = setWordFromThumbMov(*loc32, value16);
1123
8
    break;
1124
8
  case thumb_movt_funcRel:
1125
8
    assert(thumbMode);
1126
8
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
1127
8
    *loc32 = setWordFromThumbMov(*loc32, value16);
1128
8
    break;
1129
14
  case arm_b24:
1130
14
  case arm_bl24:
1131
14
    assert(!thumbMode);
1132
14
    if (useExternalReloc)
1133
6
      displacement = (ref.addend() - (fixupAddress + 8));
1134
14
    else
1135
8
      displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
1136
14
    value32 = setDisplacementInArmBranch(*loc32, displacement,
1137
14
                                         targetIsThumb);
1138
14
    *loc32 = value32;
1139
14
    break;
1140
10
  case arm_movw:
1141
10
    assert(!thumbMode);
1142
10
    if (useExternalReloc)
1143
4
      value16 = ref.addend() & 0xFFFF;
1144
10
    else
1145
6
      value16 = (targetAddress + ref.addend()) & 0xFFFF;
1146
10
    *loc32 = setWordFromArmMov(*loc32, value16);
1147
10
    break;
1148
10
  case arm_movt:
1149
10
    assert(!thumbMode);
1150
10
    if (useExternalReloc)
1151
4
      value16 = ref.addend() >> 16;
1152
10
    else
1153
6
      value16 = (targetAddress + ref.addend()) >> 16;
1154
10
    *loc32 = setWordFromArmMov(*loc32, value16);
1155
10
    break;
1156
6
  case arm_movw_funcRel:
1157
6
    assert(!thumbMode);
1158
6
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
1159
6
    *loc32 = setWordFromArmMov(*loc32, value16);
1160
6
    break;
1161
6
  case arm_movt_funcRel:
1162
6
    assert(!thumbMode);
1163
6
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
1164
6
    *loc32 = setWordFromArmMov(*loc32, value16);
1165
6
    break;
1166
12
  case pointer32:
1167
12
    *loc32 = targetAddress + ref.addend();
1168
12
    break;
1169
8
  case delta32:
1170
8
    *loc32 = targetAddress - fixupAddress + ref.addend();
1171
8
    break;
1172
0
  case lazyPointer:
1173
0
  case lazyImmediateLocation:
1174
0
    // do nothing
1175
0
    break;
1176
0
  case invalid:
1177
0
    llvm_unreachable("invalid ARM Reference Kind");
1178
0
    break;
1179
155
  }
1180
155
}
1181
1182
void ArchHandler_arm::appendSectionRelocations(
1183
                                   const DefinedAtom &atom,
1184
                                   uint64_t atomSectionOffset,
1185
                                   const Reference &ref,
1186
                                   FindSymbolIndexForAtom symbolIndexForAtom,
1187
                                   FindSectionIndexForAtom sectionIndexForAtom,
1188
                                   FindAddressForAtom addressForAtom,
1189
157
                                   normalized::Relocations &relocs) {
1190
157
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
1191
2
    return;
1192
157
  assert(ref.kindArch() == Reference::KindArch::ARM);
1193
155
  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
1194
155
  bool useExternalReloc = useExternalRelocationTo(*ref.target());
1195
155
  uint32_t targetAtomAddress;
1196
155
  uint32_t fromAtomAddress;
1197
155
  uint16_t other16;
1198
155
  switch (static_cast<ArmKind>(ref.kindValue())) {
1199
31
  case modeThumbCode:
1200
31
  case modeArmCode:
1201
31
  case modeData:
1202
31
    // Do nothing.
1203
31
    break;
1204
18
  case thumb_b22:
1205
18
  case thumb_bl22:
1206
18
    if (
useExternalReloc18
) {
1207
6
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1208
6
                  ARM_THUMB_RELOC_BR22 | rExtern    | rPcRel | rLength4);
1209
18
    } else {
1210
12
      if (ref.addend() != 0)
1211
2
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1212
2
                  ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4);
1213
12
      else
1214
10
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1215
10
                  ARM_THUMB_RELOC_BR22 |              rPcRel | rLength4);
1216
12
    }
1217
18
    break;
1218
12
  case thumb_movw:
1219
12
    if (
useExternalReloc12
) {
1220
4
      other16 = ref.addend() >> 16;
1221
4
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1222
4
                  ARM_RELOC_HALF | rExtern    | rLenThmbLo);
1223
4
      appendReloc(relocs, other16, 0, 0,
1224
4
                  ARM_RELOC_PAIR              | rLenThmbLo);
1225
12
    } else {
1226
8
      targetAtomAddress = addressForAtom(*ref.target());
1227
8
      if (
ref.addend() != 08
) {
1228
2
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1229
2
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1230
2
                  ARM_RELOC_HALF | rScattered | rLenThmbLo);
1231
2
        appendReloc(relocs, other16, 0, 0,
1232
2
                  ARM_RELOC_PAIR              | rLenThmbLo);
1233
8
      } else {
1234
6
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1235
6
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1236
6
                  ARM_RELOC_HALF              | rLenThmbLo);
1237
6
        appendReloc(relocs, other16, 0, 0,
1238
6
                  ARM_RELOC_PAIR              | rLenThmbLo);
1239
6
      }
1240
8
    }
1241
12
    break;
1242
12
  case thumb_movt:
1243
12
    if (
useExternalReloc12
) {
1244
4
      other16 = ref.addend() & 0xFFFF;
1245
4
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1246
4
                  ARM_RELOC_HALF | rExtern    | rLenThmbHi);
1247
4
      appendReloc(relocs, other16, 0, 0,
1248
4
                  ARM_RELOC_PAIR              | rLenThmbHi);
1249
12
    } else {
1250
8
      targetAtomAddress = addressForAtom(*ref.target());
1251
8
      if (
ref.addend() != 08
) {
1252
2
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1253
2
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1254
2
                    ARM_RELOC_HALF | rScattered | rLenThmbHi);
1255
2
        appendReloc(relocs, other16, 0, 0,
1256
2
                    ARM_RELOC_PAIR              | rLenThmbHi);
1257
8
      } else {
1258
6
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1259
6
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1260
6
                    ARM_RELOC_HALF              | rLenThmbHi);
1261
6
        appendReloc(relocs, other16, 0, 0,
1262
6
                    ARM_RELOC_PAIR              | rLenThmbHi);
1263
6
      }
1264
8
    }
1265
12
    break;
1266
8
  case thumb_movw_funcRel:
1267
8
    fromAtomAddress = addressForAtom(atom);
1268
8
    targetAtomAddress = addressForAtom(*ref.target());
1269
8
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
1270
8
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1271
8
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbLo);
1272
8
    appendReloc(relocs, other16, 0, fromAtomAddress,
1273
8
                ARM_RELOC_PAIR          | rScattered | rLenThmbLo);
1274
8
    break;
1275
8
  case thumb_movt_funcRel:
1276
8
    fromAtomAddress = addressForAtom(atom);
1277
8
    targetAtomAddress = addressForAtom(*ref.target());
1278
8
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
1279
8
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1280
8
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbHi);
1281
8
    appendReloc(relocs, other16, 0, fromAtomAddress,
1282
8
                ARM_RELOC_PAIR          | rScattered | rLenThmbHi);
1283
8
    break;
1284
14
  case arm_b24:
1285
14
  case arm_bl24:
1286
14
    if (
useExternalReloc14
) {
1287
6
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1288
6
                  ARM_RELOC_BR24 | rExtern    | rPcRel | rLength4);
1289
14
    } else {
1290
8
      if (ref.addend() != 0)
1291
2
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1292
2
                  ARM_RELOC_BR24 | rScattered | rPcRel | rLength4);
1293
8
      else
1294
6
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1295
6
                  ARM_RELOC_BR24 |              rPcRel | rLength4);
1296
8
    }
1297
14
    break;
1298
10
  case arm_movw:
1299
10
    if (
useExternalReloc10
) {
1300
4
      other16 = ref.addend() >> 16;
1301
4
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1302
4
                  ARM_RELOC_HALF | rExtern    | rLenArmLo);
1303
4
      appendReloc(relocs, other16, 0, 0,
1304
4
                  ARM_RELOC_PAIR              | rLenArmLo);
1305
10
    } else {
1306
6
      targetAtomAddress = addressForAtom(*ref.target());
1307
6
      if (
ref.addend() != 06
) {
1308
2
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1309
2
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1310
2
                  ARM_RELOC_HALF | rScattered | rLenArmLo);
1311
2
        appendReloc(relocs, other16, 0, 0,
1312
2
                  ARM_RELOC_PAIR              | rLenArmLo);
1313
6
      } else {
1314
4
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1315
4
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1316
4
                  ARM_RELOC_HALF              | rLenArmLo);
1317
4
        appendReloc(relocs, other16, 0, 0,
1318
4
                  ARM_RELOC_PAIR              | rLenArmLo);
1319
4
      }
1320
6
    }
1321
10
    break;
1322
10
  case arm_movt:
1323
10
    if (
useExternalReloc10
) {
1324
4
      other16 = ref.addend() & 0xFFFF;
1325
4
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1326
4
                  ARM_RELOC_HALF | rExtern    | rLenArmHi);
1327
4
      appendReloc(relocs, other16, 0, 0,
1328
4
                  ARM_RELOC_PAIR              | rLenArmHi);
1329
10
    } else {
1330
6
      targetAtomAddress = addressForAtom(*ref.target());
1331
6
      if (
ref.addend() != 06
) {
1332
2
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1333
2
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1334
2
                  ARM_RELOC_HALF | rScattered | rLenArmHi);
1335
2
        appendReloc(relocs, other16, 0, 0,
1336
2
                  ARM_RELOC_PAIR              | rLenArmHi);
1337
6
      } else {
1338
4
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1339
4
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1340
4
                  ARM_RELOC_HALF              | rLenArmHi);
1341
4
        appendReloc(relocs, other16, 0, 0,
1342
4
                  ARM_RELOC_PAIR              | rLenArmHi);
1343
4
      }
1344
6
    }
1345
10
    break;
1346
6
  case arm_movw_funcRel:
1347
6
    fromAtomAddress = addressForAtom(atom);
1348
6
    targetAtomAddress = addressForAtom(*ref.target());
1349
6
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
1350
6
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1351
6
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmLo);
1352
6
    appendReloc(relocs, other16, 0, fromAtomAddress,
1353
6
                ARM_RELOC_PAIR          | rScattered | rLenArmLo);
1354
6
    break;
1355
6
  case arm_movt_funcRel:
1356
6
    fromAtomAddress = addressForAtom(atom);
1357
6
    targetAtomAddress = addressForAtom(*ref.target());
1358
6
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
1359
6
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1360
6
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmHi);
1361
6
    appendReloc(relocs, other16, 0, fromAtomAddress,
1362
6
                ARM_RELOC_PAIR          | rScattered | rLenArmHi);
1363
6
    break;
1364
12
  case pointer32:
1365
12
    if (
useExternalReloc12
) {
1366
4
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
1367
4
                ARM_RELOC_VANILLA |    rExtern     |  rLength4);
1368
4
    }
1369
8
    else {
1370
8
      if (ref.addend() != 0)
1371
2
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1372
2
                ARM_RELOC_VANILLA |    rScattered  |  rLength4);
1373
8
      else
1374
6
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1375
6
                ARM_RELOC_VANILLA |                   rLength4);
1376
8
    }
1377
12
    break;
1378
8
  case delta32:
1379
8
    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1380
8
              ARM_RELOC_SECTDIFF  |  rScattered    | rLength4);
1381
8
    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
1382
8
                                                           ref.offsetInAtom(),
1383
8
              ARM_RELOC_PAIR      |  rScattered    | rLength4);
1384
8
    break;
1385
0
  case lazyPointer:
1386
0
  case lazyImmediateLocation:
1387
0
    // do nothing
1388
0
    break;
1389
0
  case invalid:
1390
0
    llvm_unreachable("invalid ARM Reference Kind");
1391
0
    break;
1392
155
  }
1393
155
}
1394
1395
47
void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) {
1396
47
  if (
atom.isThumb()47
) {
1397
20
    atom.addReference(Reference::KindNamespace::mach_o,
1398
20
                      Reference::KindArch::ARM, modeThumbCode, 0, &atom, 0);
1399
20
  }
1400
47
}
1401
1402
299
bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) {
1403
284
  for (const Reference *ref : atom) {
1404
284
    if (ref->offsetInAtom() != 0)
1405
120
      return false;
1406
164
    
if (164
ref->kindNamespace() != Reference::KindNamespace::mach_o164
)
1407
3
      continue;
1408
164
    assert(ref->kindArch() == Reference::KindArch::ARM);
1409
161
    if (ref->kindValue() == modeThumbCode)
1410
131
      return true;
1411
48
  }
1412
48
  return false;
1413
48
}
1414
1415
class Thumb2ToArmShimAtom : public SimpleDefinedAtom {
1416
public:
1417
  Thumb2ToArmShimAtom(MachOFile &file, StringRef targetName,
1418
                      const DefinedAtom &target)
1419
2
      : SimpleDefinedAtom(file) {
1420
2
    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
1421
2
                 ArchHandler_arm::modeThumbCode, 0, this, 0);
1422
2
    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
1423
2
                 ArchHandler_arm::delta32, 8, &target, 0);
1424
2
    std::string name = std::string(targetName) + "$shim";
1425
2
    StringRef tmp(name);
1426
2
    _name = tmp.copy(file.allocator());
1427
2
  }
1428
1429
2
  ~Thumb2ToArmShimAtom() override = default;
1430
1431
9
  StringRef name() const override {
1432
9
    return _name;
1433
9
  }
1434
1435
16
  ContentType contentType() const override {
1436
16
    return DefinedAtom::typeCode;
1437
16
  }
1438
1439
2
  Alignment alignment() const override { return 4; }
1440
1441
8
  uint64_t size() const override {
1442
8
    return 12;
1443
8
  }
1444
1445
0
  ContentPermissions permissions() const override {
1446
0
    return DefinedAtom::permR_X;
1447
0
  }
1448
1449
4
  ArrayRef<uint8_t> rawContent() const override {
1450
4
    static const uint8_t bytes[] =
1451
4
    { 0xDF, 0xF8, 0x04, 0xC0,       //  ldr ip, pc + 4
1452
4
      0xFF, 0x44,                   //  add ip, pc, ip
1453
4
      0x60, 0x47,                   //  ldr pc, [ip]
1454
4
      0x00, 0x00, 0x00, 0x00 };     //  .long target - this
1455
4
    assert(sizeof(bytes) == size());
1456
4
    return llvm::makeArrayRef(bytes, sizeof(bytes));
1457
4
  }
1458
private:
1459
  StringRef _name;
1460
};
1461
1462
class ArmToThumbShimAtom : public SimpleDefinedAtom {
1463
public:
1464
  ArmToThumbShimAtom(MachOFile &file, StringRef targetName,
1465
                     const DefinedAtom &target)
1466
2
      : SimpleDefinedAtom(file) {
1467
2
    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
1468
2
                 ArchHandler_arm::delta32, 12, &target, 0);
1469
2
    std::string name = std::string(targetName) + "$shim";
1470
2
    StringRef tmp(name);
1471
2
    _name = tmp.copy(file.allocator());
1472
2
  }
1473
1474
2
  ~ArmToThumbShimAtom() override = default;
1475
1476
9
  StringRef name() const override {
1477
9
    return _name;
1478
9
  }
1479
1480
16
  ContentType contentType() const override {
1481
16
    return DefinedAtom::typeCode;
1482
16
  }
1483
1484
2
  Alignment alignment() const override { return 4; }
1485
1486
8
  uint64_t size() const override {
1487
8
    return 16;
1488
8
  }
1489
1490
0
  ContentPermissions permissions() const override {
1491
0
    return DefinedAtom::permR_X;
1492
0
  }
1493
1494
4
  ArrayRef<uint8_t> rawContent() const override {
1495
4
    static const uint8_t bytes[] =
1496
4
    { 0x04, 0xC0, 0x9F, 0xE5,       //  ldr ip, pc + 4
1497
4
      0x0C, 0xC0, 0x8F, 0xE0,       //  add ip, pc, ip
1498
4
      0x1C, 0xFF, 0x2F, 0xE1,       //  ldr pc, [ip]
1499
4
      0x00, 0x00, 0x00, 0x00 };     //  .long target - this
1500
4
    assert(sizeof(bytes) == size());
1501
4
    return llvm::makeArrayRef(bytes, sizeof(bytes));
1502
4
  }
1503
private:
1504
  StringRef _name;
1505
};
1506
1507
const DefinedAtom *ArchHandler_arm::createShim(MachOFile &file,
1508
                                               bool thumbToArm,
1509
4
                                               const DefinedAtom &target) {
1510
4
  bool isStub = (target.contentType() == DefinedAtom::typeStub);
1511
4
  StringRef targetName = isStub ? 
stubName(target)0
:
target.name()4
;
1512
4
  if (thumbToArm)
1513
2
    return new (file.allocator()) Thumb2ToArmShimAtom(file, targetName, target);
1514
4
  else
1515
2
    return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target);
1516
0
}
1517
1518
33
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
1519
33
  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
1520
33
}
1521
1522
} // namespace mach_o
1523
} // namespace lld