Coverage Report

Created: 2018-01-17 21:32

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/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
16
  ArchHandler_arm() = default;
32
16
  ~ArchHandler_arm() override = default;
33
34
9
  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
35
36
108
  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
4
  bool needsCompactUnwind() override {
45
4
    return false;
46
4
  }
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
1
  Reference::KindValue lazyImmediateLocationKind() override {
71
1
    return lazyImmediateLocation;
72
1
  }
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
125
  bool isDataInCodeTransition(Reference::KindValue refKind) override {
121
125
    switch (refKind) {
122
125
    case modeThumbCode:
123
23
    case modeArmCode:
124
23
    case modeData:
125
23
      return true;
126
102
    default:
127
102
      return false;
128
23
      
break0
;
129
0
    }
130
0
  }
131
132
  Reference::KindValue dataInCodeTransitionStart(
133
8
                                        const MachODefinedAtom &atom) override {
134
8
    return modeData;
135
8
  }
136
137
  Reference::KindValue dataInCodeTransitionEnd(
138
2
                                        const MachODefinedAtom &atom) override {
139
2
    return atom.isThumb() ? 
modeThumbCode1
:
modeArmCode1
;
140
2
  }
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
69
const ArchHandler::StubInfo &ArchHandler_arm::stubInfo() {
297
69
  // If multiple kinds of stubs are supported, select which StubInfo here.
298
69
  return _sStubInfoArmPIC;
299
69
}
300
301
44
bool ArchHandler_arm::isCallSite(const Reference &ref) {
302
44
  switch (ref.kindValue()) {
303
44
  case thumb_b22:
304
21
  case thumb_bl22:
305
21
  case arm_b24:
306
21
  case arm_bl24:
307
21
    return true;
308
23
  default:
309
23
    return false;
310
0
  }
311
0
}
312
313
59
bool ArchHandler_arm::isPointer(const Reference &ref) {
314
59
  return (ref.kindValue() == pointer32);
315
59
}
316
317
53
bool ArchHandler_arm::isNonCallBranch(const Reference &ref) {
318
53
  switch (ref.kindValue()) {
319
53
  case thumb_b22:
320
5
  case arm_b24:
321
5
    return true;
322
48
  default:
323
48
    return false;
324
0
  }
325
0
}
326
327
89
bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) {
328
89
  switch (reloc.type) {
329
89
  case ARM_RELOC_SECTDIFF:
330
50
  case ARM_RELOC_LOCAL_SECTDIFF:
331
50
  case ARM_RELOC_HALF_SECTDIFF:
332
50
  case ARM_RELOC_HALF:
333
50
    return true;
334
50
  default:
335
39
    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* lp = dyn_cast<DefinedAtom>(ref->target())) {
344
0
      if (lp->contentType() != DefinedAtom::typeLazyPointer)
345
0
        continue;
346
0
      for (const Reference *ref2 : *lp) {
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
13
int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
358
13
  // Sign-extend imm24
359
13
  int32_t displacement = (instruction & 0x00FFFFFF) << 2;
360
13
  if ((displacement & 0x02000000) != 0)
361
10
    displacement |= 0xFC000000;
362
13
  // If this is BLX and H bit set, add 2.
363
13
  if ((instruction & 0xFF000000) == 0xFB000000)
364
0
    displacement += 2;
365
13
  return displacement;
366
13
}
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
14
                                                     bool targetIsThumb) {
372
14
  assert((displacement <= 33554428) && (displacement > (-33554432))
373
14
                                              && "arm branch out of range");
374
14
  bool is_blx = ((instruction & 0xF0000000) == 0xF0000000);
375
14
  uint32_t newInstruction = (instruction & 0xFF000000);
376
14
  uint32_t h = 0;
377
14
  if (targetIsThumb) {
378
4
    // Force use of BLX.
379
4
    newInstruction = 0xFA000000;
380
4
    if (!is_blx) {
381
0
      assert(((instruction & 0xF0000000) == 0xE0000000)
382
0
                                                   && "no conditional arm blx");
383
0
      assert(((instruction & 0xFF000000) == 0xEB000000)
384
0
                                             && "no arm pc-rel BX instruction");
385
0
    }
386
4
    if (displacement & 2)
387
0
      h = 1;
388
4
  }
389
10
  else {
390
10
    // Force use of B/BL.
391
10
    if (is_blx)
392
0
      newInstruction = 0xEB000000;
393
10
  }
394
14
  newInstruction |= (h << 24) | ((displacement >> 2) & 0x00FFFFFF);
395
14
  return newInstruction;
396
14
}
397
398
/// Extract displacement from a thumb b/bl/blx instruction.
399
int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction,
400
18
                                                        uint32_t instrAddr) {
401
18
  bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
402
18
  uint32_t s = (instruction >> 10) & 0x1;
403
18
  uint32_t j1 = (instruction >> 29) & 0x1;
404
18
  uint32_t j2 = (instruction >> 27) & 0x1;
405
18
  uint32_t imm10 = instruction & 0x3FF;
406
18
  uint32_t imm11 = (instruction >> 16) & 0x7FF;
407
18
  uint32_t i1 = (j1 == s);
408
18
  uint32_t i2 = (j2 == s);
409
18
  uint32_t dis =
410
18
      (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
411
18
  int32_t sdis = dis;
412
18
  int32_t result = s ? 
(sdis | 0xFE000000)10
:
sdis8
;
413
18
  if (is_blx && 
(instrAddr & 0x2)6
) {
414
4
    // The thumb blx instruction always has low bit of imm11 as zero.  The way
415
4
    // a 2-byte aligned blx can branch to a 4-byte aligned ARM target is that
416
4
    // the blx instruction always 4-byte aligns the pc before adding the
417
4
    // displacement from the blx.  We must emulate that when decoding this.
418
4
    result -= 2;
419
4
  }
420
18
  return result;
421
18
}
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
18
                                                       bool targetIsThumb) {
428
18
  assert((displacement <= 16777214) && (displacement > (-16777216))
429
18
                                              && "thumb branch out of range");
430
18
  bool is_bl = ((instruction & 0xD000F800) == 0xD000F000);
431
18
  bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
432
18
  bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
433
18
  uint32_t newInstruction = (instruction & 0xD000F800);
434
18
  if (is_bl || 
is_blx9
) {
435
15
    if (targetIsThumb) {
436
7
      newInstruction = 0xD000F000; // Use bl
437
8
    } else {
438
8
      newInstruction = 0xC000F000; // Use blx
439
8
      // See note in getDisplacementFromThumbBranch() about blx.
440
8
      if (instrAddr & 0x2)
441
3
        displacement += 2;
442
8
    }
443
15
  } else 
if (3
is_b3
) {
444
3
    assert(targetIsThumb && "no pc-rel thumb branch instruction that "
445
3
                             "switches to arm mode");
446
3
  }
447
0
  else {
448
0
    llvm_unreachable("thumb branch22 reloc on a non-branch instruction");
449
0
  }
450
18
  uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
451
18
  uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
452
18
  uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
453
18
  uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF;
454
18
  uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF;
455
18
  uint32_t j1 = (i1 == s);
456
18
  uint32_t j2 = (i2 == s);
457
18
  uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11;
458
18
  uint32_t firstDisp = (s << 10) | imm10;
459
18
  newInstruction |= (nextDisp << 16) | firstDisp;
460
18
  return newInstruction;
461
18
}
462
463
13
bool ArchHandler_arm::isThumbMovw(uint32_t instruction) {
464
13
  return (instruction & 0x8000FBF0) == 0x0000F240;
465
13
}
466
467
13
bool ArchHandler_arm::isThumbMovt(uint32_t instruction) {
468
13
  return (instruction & 0x8000FBF0) == 0x0000F2C0;
469
13
}
470
471
10
bool ArchHandler_arm::isArmMovw(uint32_t instruction) {
472
10
  return (instruction & 0x0FF00000) == 0x03000000;
473
10
}
474
475
10
bool ArchHandler_arm::isArmMovt(uint32_t instruction) {
476
10
  return (instruction & 0x0FF00000) == 0x03400000;
477
10
}
478
479
26
uint16_t ArchHandler_arm::getWordFromThumbMov(uint32_t instruction) {
480
26
  assert(isThumbMovw(instruction) || isThumbMovt(instruction));
481
26
  uint32_t i = ((instruction & 0x00000400) >> 10);
482
26
  uint32_t imm4 = (instruction & 0x0000000F);
483
26
  uint32_t imm3 = ((instruction & 0x70000000) >> 28);
484
26
  uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
485
26
  return (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
486
26
}
487
488
20
uint16_t ArchHandler_arm::getWordFromArmMov(uint32_t instruction) {
489
20
  assert(isArmMovw(instruction) || isArmMovt(instruction));
490
20
  uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
491
20
  uint32_t imm12 = (instruction & 0x00000FFF);
492
20
  return (imm4 << 12) | imm12;
493
20
}
494
495
26
uint32_t ArchHandler_arm::setWordFromThumbMov(uint32_t instr, uint16_t word) {
496
26
  assert(isThumbMovw(instr) || isThumbMovt(instr));
497
26
  uint32_t imm4 = (word & 0xF000) >> 12;
498
26
  uint32_t i =    (word & 0x0800) >> 11;
499
26
  uint32_t imm3 = (word & 0x0700) >> 8;
500
26
  uint32_t imm8 =  word & 0x00FF;
501
26
  return (instr & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
502
26
}
503
504
20
uint32_t ArchHandler_arm::setWordFromArmMov(uint32_t instr, uint16_t word) {
505
20
  assert(isArmMovw(instr) || isArmMovt(instr));
506
20
  uint32_t imm4 = (word & 0xF000) >> 12;
507
20
  uint32_t imm12 = word & 0x0FFF;
508
20
  return (instr & 0xFFF0F000) | (imm4 << 16) | imm12;
509
20
}
510
511
30
uint32_t ArchHandler_arm::clearThumbBit(uint32_t value, const Atom *target) {
512
30
  // The assembler often adds one to the address of a thumb function.
513
30
  // We need to undo that so it does not look like an addend.
514
30
  if (value & 1) {
515
7
    if (isa<DefinedAtom>(target)) {
516
7
      const MachODefinedAtom *machoTarget =
517
7
          reinterpret_cast<const MachODefinedAtom *>(target);
518
7
      if (machoTarget->isThumb())
519
7
        value &= -2; // mask off thumb-bit
520
7
    }
521
7
  }
522
30
  return value;
523
30
}
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
39
    const lld::Atom **target, Reference::Addend *addend) {
531
39
  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
532
39
  uint64_t targetAddress;
533
39
  uint32_t instruction = *(const ulittle32_t *)fixupContent;
534
39
  int32_t displacement;
535
39
  switch (relocPattern(reloc)) {
536
39
  case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4:
537
8
    // ex: bl _foo (and _foo is undefined)
538
8
    if ((instruction & 0xD000F800) == 0x9000F000)
539
3
      *kind = thumb_b22;
540
5
    else
541
5
      *kind = thumb_bl22;
542
8
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
543
0
      return ec;
544
8
    // Instruction contains branch to addend.
545
8
    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
546
8
    *addend = fixupAddress + 4 + displacement;
547
8
    return llvm::Error::success();
548
9
  case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
549
9
    // ex: bl _foo (and _foo is defined)
550
9
    if ((instruction & 0xD000F800) == 0x9000F000)
551
0
      *kind = thumb_b22;
552
9
    else
553
9
      *kind = thumb_bl22;
554
9
    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
555
9
    targetAddress = fixupAddress + 4 + displacement;
556
9
    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
557
8
  case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4:
558
1
    // ex: bl _foo+4 (and _foo is defined)
559
1
    if ((instruction & 0xD000F800) == 0x9000F000)
560
0
      *kind = thumb_b22;
561
1
    else
562
1
      *kind = thumb_bl22;
563
1
    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
564
1
    targetAddress = fixupAddress + 4 + displacement;
565
1
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
566
0
      return ec;
567
1
    // reloc.value is target atom's address.  Instruction contains branch
568
1
    // to atom+addend.
569
1
    *addend += (targetAddress - reloc.value);
570
1
    return llvm::Error::success();
571
7
  case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
572
7
    // ex: bl _foo (and _foo is undefined)
573
7
    if (((instruction & 0x0F000000) == 0x0A000000)
574
7
        && 
((instruction & 0xF0000000) != 0xF0000000)5
)
575
3
      *kind = arm_b24;
576
4
    else
577
4
      *kind = arm_bl24;
578
7
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
579
0
      return ec;
580
7
    // Instruction contains branch to addend.
581
7
    displacement = getDisplacementFromArmBranch(instruction);
582
7
    *addend = fixupAddress + 8 + displacement;
583
7
    return llvm::Error::success();
584
7
  case ARM_RELOC_BR24 | rPcRel | rLength4:
585
5
    // ex: bl _foo (and _foo is defined)
586
5
    if (((instruction & 0x0F000000) == 0x0A000000)
587
5
        && 
((instruction & 0xF0000000) != 0xF0000000)2
)
588
0
      *kind = arm_b24;
589
5
    else
590
5
      *kind = arm_bl24;
591
5
    displacement = getDisplacementFromArmBranch(instruction);
592
5
    targetAddress = fixupAddress + 8 + displacement;
593
5
    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
594
7
  case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4:
595
1
    // ex: bl _foo+4 (and _foo is defined)
596
1
    if (((instruction & 0x0F000000) == 0x0A000000)
597
1
        && 
((instruction & 0xF0000000) != 0xF0000000)0
)
598
0
      *kind = arm_b24;
599
1
    else
600
1
      *kind = arm_bl24;
601
1
    displacement = getDisplacementFromArmBranch(instruction);
602
1
    targetAddress = fixupAddress + 8 + displacement;
603
1
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
604
0
      return ec;
605
1
    // reloc.value is target atom's address.  Instruction contains branch
606
1
    // to atom+addend.
607
1
    *addend += (targetAddress - reloc.value);
608
1
    return llvm::Error::success();
609
2
  case ARM_RELOC_VANILLA | rExtern | rLength4:
610
2
    // ex: .long _foo (and _foo is undefined)
611
2
    *kind = pointer32;
612
2
    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
613
0
      return ec;
614
2
    *addend = instruction;
615
2
    return llvm::Error::success();
616
5
  case ARM_RELOC_VANILLA | rLength4:
617
5
    // ex: .long _foo (and _foo is defined)
618
5
    *kind = pointer32;
619
5
    if (auto ec = atomFromAddress(reloc.symbol, instruction, target, addend))
620
0
      return ec;
621
5
    *addend = clearThumbBit((uint32_t) * addend, *target);
622
5
    return llvm::Error::success();
623
5
  case ARM_RELOC_VANILLA | rScattered | rLength4:
624
1
    // ex: .long _foo+a (and _foo is defined)
625
1
    *kind = pointer32;
626
1
    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
627
0
      return ec;
628
1
    *addend += (clearThumbBit(instruction, *target) - reloc.value);
629
1
    return llvm::Error::success();
630
1
  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
50
                                     Reference::Addend *addend) {
648
50
  bool pointerDiff = false;
649
50
  bool funcRel;
650
50
  bool top;
651
50
  bool thumbReloc;
652
50
  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
653
50
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenThmbLo) << 16 |
654
6
         ARM_RELOC_PAIR           | rScattered | rLenThmbLo):
655
6
    // ex: movw r1, :lower16:(_x-L1) [thumb mode]
656
6
    *kind = thumb_movw_funcRel;
657
6
    funcRel = true;
658
6
    top = false;
659
6
    thumbReloc = true;
660
6
    break;
661
50
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenThmbHi) << 16 |
662
6
         ARM_RELOC_PAIR           | rScattered | rLenThmbHi):
663
6
    // ex: movt r1, :upper16:(_x-L1) [thumb mode]
664
6
    *kind = thumb_movt_funcRel;
665
6
    funcRel = true;
666
6
    top = true;
667
6
    thumbReloc = true;
668
6
    break;
669
50
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenArmLo) << 16 |
670
4
         ARM_RELOC_PAIR           | rScattered | rLenArmLo):
671
4
    // ex: movw r1, :lower16:(_x-L1) [arm mode]
672
4
    *kind = arm_movw_funcRel;
673
4
    funcRel = true;
674
4
    top = false;
675
4
    thumbReloc = false;
676
4
    break;
677
50
  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenArmHi) << 16 |
678
4
         ARM_RELOC_PAIR           | rScattered | rLenArmHi):
679
4
    // ex: movt r1, :upper16:(_x-L1) [arm mode]
680
4
    *kind = arm_movt_funcRel;
681
4
    funcRel = true;
682
4
    top = true;
683
4
    thumbReloc = false;
684
4
    break;
685
50
  case ((ARM_RELOC_HALF     | rLenThmbLo) << 16 |
686
4
         ARM_RELOC_PAIR     | rLenThmbLo):
687
4
    // ex: movw r1, :lower16:_x [thumb mode]
688
4
    *kind = thumb_movw;
689
4
    funcRel = false;
690
4
    top = false;
691
4
    thumbReloc = true;
692
4
    break;
693
50
  case ((ARM_RELOC_HALF     | rLenThmbHi) << 16 |
694
4
         ARM_RELOC_PAIR     | rLenThmbHi):
695
4
    // ex: movt r1, :upper16:_x [thumb mode]
696
4
    *kind = thumb_movt;
697
4
    funcRel = false;
698
4
    top = true;
699
4
    thumbReloc = true;
700
4
    break;
701
50
  case ((ARM_RELOC_HALF     | rLenArmLo) << 16 |
702
3
         ARM_RELOC_PAIR     | rLenArmLo):
703
3
    // ex: movw r1, :lower16:_x [arm mode]
704
3
    *kind = arm_movw;
705
3
    funcRel = false;
706
3
    top = false;
707
3
    thumbReloc = false;
708
3
    break;
709
50
  case ((ARM_RELOC_HALF     | rLenArmHi) << 16 |
710
3
         ARM_RELOC_PAIR     | rLenArmHi):
711
3
    // ex: movt r1, :upper16:_x [arm mode]
712
3
    *kind = arm_movt;
713
3
    funcRel = false;
714
3
    top = true;
715
3
    thumbReloc = false;
716
3
    break;
717
50
  case ((ARM_RELOC_HALF | rScattered  | rLenThmbLo) << 16 |
718
1
         ARM_RELOC_PAIR               | rLenThmbLo):
719
1
    // ex: movw r1, :lower16:_x+a [thumb mode]
720
1
    *kind = thumb_movw;
721
1
    funcRel = false;
722
1
    top = false;
723
1
    thumbReloc = true;
724
1
    break;
725
50
  case ((ARM_RELOC_HALF | rScattered  | rLenThmbHi) << 16 |
726
1
         ARM_RELOC_PAIR               | rLenThmbHi):
727
1
    // ex: movt r1, :upper16:_x+a [thumb mode]
728
1
    *kind = thumb_movt;
729
1
    funcRel = false;
730
1
    top = true;
731
1
    thumbReloc = true;
732
1
    break;
733
50
  case ((ARM_RELOC_HALF | rScattered  | rLenArmLo) << 16 |
734
1
         ARM_RELOC_PAIR               | rLenArmLo):
735
1
    // ex: movw r1, :lower16:_x+a [arm mode]
736
1
    *kind = arm_movw;
737
1
    funcRel = false;
738
1
    top = false;
739
1
    thumbReloc = false;
740
1
    break;
741
50
  case ((ARM_RELOC_HALF | rScattered  | rLenArmHi) << 16 |
742
1
         ARM_RELOC_PAIR               | rLenArmHi):
743
1
    // ex: movt r1, :upper16:_x+a [arm mode]
744
1
    *kind = arm_movt;
745
1
    funcRel = false;
746
1
    top = true;
747
1
    thumbReloc = false;
748
1
    break;
749
50
  case ((ARM_RELOC_HALF | rExtern   | rLenThmbLo) << 16 |
750
2
         ARM_RELOC_PAIR             | rLenThmbLo):
751
2
    // ex: movw r1, :lower16:_undef [thumb mode]
752
2
    *kind = thumb_movw;
753
2
    funcRel = false;
754
2
    top = false;
755
2
    thumbReloc = true;
756
2
    break;
757
50
  case ((ARM_RELOC_HALF | rExtern   | rLenThmbHi) << 16 |
758
2
         ARM_RELOC_PAIR             | rLenThmbHi):
759
2
    // ex: movt r1, :upper16:_undef [thumb mode]
760
2
    *kind = thumb_movt;
761
2
    funcRel = false;
762
2
    top = true;
763
2
    thumbReloc = true;
764
2
    break;
765
50
  case ((ARM_RELOC_HALF | rExtern   | rLenArmLo) << 16 |
766
2
         ARM_RELOC_PAIR             | rLenArmLo):
767
2
    // ex: movw r1, :lower16:_undef [arm mode]
768
2
    *kind = arm_movw;
769
2
    funcRel = false;
770
2
    top = false;
771
2
    thumbReloc = false;
772
2
    break;
773
50
  case ((ARM_RELOC_HALF | rExtern   | rLenArmHi) << 16 |
774
2
         ARM_RELOC_PAIR             | rLenArmHi):
775
2
    // ex: movt r1, :upper16:_undef [arm mode]
776
2
    *kind = arm_movt;
777
2
    funcRel = false;
778
2
    top = true;
779
2
    thumbReloc = false;
780
2
    break;
781
50
  case ((ARM_RELOC_SECTDIFF       | rScattered | rLength4) << 16 |
782
4
         ARM_RELOC_PAIR           | rScattered | rLength4):
783
4
  case ((ARM_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
784
4
         ARM_RELOC_PAIR           | rScattered | rLength4):
785
4
    // ex: .long _foo - .
786
4
    pointerDiff = true;
787
4
    break;
788
4
  default:
789
0
    return llvm::make_error<GenericError>("unsupported arm relocation pair");
790
50
  }
791
50
  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
792
50
  uint32_t instruction = *(const ulittle32_t *)fixupContent;
793
50
  uint32_t value;
794
50
  uint32_t fromAddress;
795
50
  uint32_t toAddress;
796
50
  uint16_t instruction16;
797
50
  uint16_t other16;
798
50
  const lld::Atom *fromTarget;
799
50
  Reference::Addend offsetInTo;
800
50
  Reference::Addend offsetInFrom;
801
50
  if (pointerDiff) {
802
4
    toAddress = reloc1.value;
803
4
    fromAddress = reloc2.value;
804
4
    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
805
0
      return ec;
806
4
    if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
807
0
      return ec;
808
4
    if (scatterable && (fromTarget != inAtom))
809
0
      return llvm::make_error<GenericError>(
810
0
          "SECTDIFF relocation where subtrahend label is not in atom");
811
4
    *kind = delta32;
812
4
    value = clearThumbBit(instruction, *target);
813
4
    *addend = (int32_t)(value - (toAddress - fixupAddress));
814
46
  } else if (funcRel) {
815
20
    toAddress = reloc1.value;
816
20
    fromAddress = reloc2.value;
817
20
    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
818
0
      return ec;
819
20
    if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
820
0
      return ec;
821
20
    if (fromTarget != inAtom)
822
0
      return llvm::make_error<GenericError>("ARM_RELOC_HALF_SECTDIFF relocation"
823
0
                                     " where subtrahend label is not in atom");
824
20
    other16 = (reloc2.offset & 0xFFFF);
825
20
    if (thumbReloc) {
826
12
      if (top) {
827
6
        if (!isThumbMovt(instruction))
828
0
          return llvm::make_error<GenericError>("expected movt instruction");
829
6
      }
830
6
      else {
831
6
        if (!isThumbMovw(instruction))
832
0
          return llvm::make_error<GenericError>("expected movw instruction");
833
12
      }
834
12
      instruction16 = getWordFromThumbMov(instruction);
835
12
    }
836
8
    else {
837
8
      if (top) {
838
4
        if (!isArmMovt(instruction))
839
0
          return llvm::make_error<GenericError>("expected movt instruction");
840
4
      }
841
4
      else {
842
4
        if (!isArmMovw(instruction))
843
0
          return llvm::make_error<GenericError>("expected movw instruction");
844
8
      }
845
8
      instruction16 = getWordFromArmMov(instruction);
846
8
    }
847
20
    if (top)
848
10
      value = (instruction16 << 16) | other16;
849
10
    else
850
10
      value = (other16 << 16) | instruction16;
851
20
    value = clearThumbBit(value, *target);
852
20
    int64_t ta = (int64_t) value - (toAddress - fromAddress);
853
20
    *addend = ta - offsetInFrom;
854
20
    return llvm::Error::success();
855
26
  } else {
856
26
    uint32_t sectIndex;
857
26
    if (thumbReloc) {
858
14
      if (top) {
859
7
        if (!isThumbMovt(instruction))
860
0
          return llvm::make_error<GenericError>("expected movt instruction");
861
7
      }
862
7
      else {
863
7
        if (!isThumbMovw(instruction))
864
0
          return llvm::make_error<GenericError>("expected movw instruction");
865
14
      }
866
14
      instruction16 = getWordFromThumbMov(instruction);
867
14
    }
868
12
    else {
869
12
      if (top) {
870
6
        if (!isArmMovt(instruction))
871
0
          return llvm::make_error<GenericError>("expected movt instruction");
872
6
      }
873
6
      else {
874
6
        if (!isArmMovw(instruction))
875
0
          return llvm::make_error<GenericError>("expected movw instruction");
876
12
      }
877
12
      instruction16 = getWordFromArmMov(instruction);
878
12
    }
879
26
    other16 = (reloc2.offset & 0xFFFF);
880
26
    if (top)
881
13
      value = (instruction16 << 16) | other16;
882
13
    else
883
13
      value = (other16 << 16) | instruction16;
884
26
    if (reloc1.isExtern) {
885
8
      if (auto ec = atomFromSymbolIndex(reloc1.symbol, target))
886
0
        return ec;
887
8
      *addend = value;
888
18
    } else {
889
18
      if (reloc1.scattered) {
890
4
        toAddress = reloc1.value;
891
4
        sectIndex = 0;
892
14
      } else {
893
14
        toAddress = value;
894
14
        sectIndex = reloc1.symbol;
895
14
      }
896
18
      if (auto ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo))
897
0
        return ec;
898
18
      *addend = value - toAddress;
899
18
    }
900
26
  }
901
50
902
50
  
return llvm::Error::success()30
;
903
50
}
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
59
                                      bool &thumbMode, bool targetIsThumb) {
910
59
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
911
0
    return;
912
59
  assert(ref.kindArch() == Reference::KindArch::ARM);
913
59
  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
914
59
  int32_t displacement;
915
59
  uint16_t value16;
916
59
  uint32_t value32;
917
59
  switch (static_cast<ArmKind>(ref.kindValue())) {
918
59
  case modeThumbCode:
919
10
    thumbMode = true;
920
10
    break;
921
59
  case modeArmCode:
922
1
    thumbMode = false;
923
1
    break;
924
59
  case modeData:
925
8
    break;
926
59
  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
13
  case thumb_movw:
935
0
    assert(thumbMode);
936
0
    value16 = (targetAddress + ref.addend()) & 0xFFFF;
937
0
    if (targetIsThumb)
938
0
      value16 |= 1;
939
0
    *loc32 = setWordFromThumbMov(*loc32, value16);
940
0
    break;
941
13
  case thumb_movt:
942
0
    assert(thumbMode);
943
0
    value16 = (targetAddress + ref.addend()) >> 16;
944
0
    *loc32 = setWordFromThumbMov(*loc32, value16);
945
0
    break;
946
13
  case thumb_movw_funcRel:
947
1
    assert(thumbMode);
948
1
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
949
1
    if (targetIsThumb)
950
0
      value16 |= 1;
951
1
    *loc32 = setWordFromThumbMov(*loc32, value16);
952
1
    break;
953
13
  case thumb_movt_funcRel:
954
1
    assert(thumbMode);
955
1
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
956
1
    *loc32 = setWordFromThumbMov(*loc32, value16);
957
1
    break;
958
13
  case arm_b24:
959
9
  case arm_bl24:
960
9
   assert(!thumbMode);
961
9
    displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
962
9
    value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
963
9
    *loc32 = value32;
964
9
    break;
965
9
  case arm_movw:
966
0
    assert(!thumbMode);
967
0
    value16 = (targetAddress + ref.addend()) & 0xFFFF;
968
0
    if (targetIsThumb)
969
0
      value16 |= 1;
970
0
    *loc32 = setWordFromArmMov(*loc32, value16);
971
0
    break;
972
9
  case arm_movt:
973
0
    assert(!thumbMode);
974
0
    value16 = (targetAddress + ref.addend()) >> 16;
975
0
    *loc32 = setWordFromArmMov(*loc32, value16);
976
0
    break;
977
9
  case arm_movw_funcRel:
978
0
    assert(!thumbMode);
979
0
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
980
0
    if (targetIsThumb)
981
0
      value16 |= 1;
982
0
    *loc32 = setWordFromArmMov(*loc32, value16);
983
0
    break;
984
9
  case arm_movt_funcRel:
985
0
    assert(!thumbMode);
986
0
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
987
0
    *loc32 = setWordFromArmMov(*loc32, value16);
988
0
    break;
989
9
  case pointer32:
990
6
    if (targetIsThumb)
991
2
      *loc32 = targetAddress + ref.addend() + 1;
992
4
    else
993
4
      *loc32 = targetAddress + ref.addend();
994
6
    break;
995
9
  case delta32:
996
7
    if (targetIsThumb)
997
2
      *loc32 = targetAddress - fixupAddress + ref.addend() + 1;
998
5
    else
999
5
      *loc32 = targetAddress - fixupAddress + ref.addend();
1000
7
    break;
1001
9
  case lazyPointer:
1002
1
    // do nothing
1003
1
    break;
1004
9
  case lazyImmediateLocation:
1005
2
    *loc32 = ref.addend();
1006
2
    break;
1007
9
  case invalid:
1008
0
    llvm_unreachable("invalid ARM Reference Kind");
1009
9
    
break0
;
1010
59
  }
1011
59
}
1012
1013
void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
1014
                                          bool relocatable,
1015
                                          FindAddressForAtom findAddress,
1016
                                          FindAddressForAtom findSectionAddress,
1017
                                          uint64_t imageBaseAddress,
1018
33
                            llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
1019
33
  // Copy raw bytes.
1020
33
  std::copy(atom.rawContent().begin(), atom.rawContent().end(),
1021
33
            atomContentBuffer.begin());
1022
33
  // Apply fix-ups.
1023
33
  bool thumbMode = false;
1024
125
  for (const Reference *ref : atom) {
1025
125
    uint32_t offset = ref->offsetInAtom();
1026
125
    const Atom *target = ref->target();
1027
125
    uint64_t targetAddress = 0;
1028
125
    bool targetIsThumb = false;
1029
125
    if (const DefinedAtom *defTarg = dyn_cast<DefinedAtom>(target)) {
1030
107
      targetAddress = findAddress(*target);
1031
107
      targetIsThumb = isThumbFunction(*defTarg);
1032
107
    }
1033
125
    uint64_t atomAddress = findAddress(atom);
1034
125
    uint64_t fixupAddress = atomAddress + offset;
1035
125
    if (relocatable) {
1036
66
      applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
1037
66
                            targetAddress, atomAddress, thumbMode,
1038
66
                            targetIsThumb);
1039
66
    } else {
1040
59
      applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
1041
59
                      targetAddress, atomAddress, thumbMode, targetIsThumb);
1042
59
    }
1043
125
  }
1044
33
}
1045
1046
132
bool ArchHandler_arm::useExternalRelocationTo(const Atom &target) {
1047
132
  // Undefined symbols are referenced via external relocations.
1048
132
  if (isa<UndefinedAtom>(&target))
1049
32
    return true;
1050
100
  if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
1051
100
     switch (defAtom->merge()) {
1052
100
     case DefinedAtom::mergeAsTentative:
1053
0
       // Tentative definitions are referenced via external relocations.
1054
0
       return true;
1055
100
     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
100
     default:
1060
100
       break;
1061
100
    }
1062
100
  }
1063
100
  // Everything else is reference via an internal relocation.
1064
100
  return false;
1065
100
}
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
66
                                            bool targetIsThumb) {
1073
66
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
1074
0
    return;
1075
66
  assert(ref.kindArch() == Reference::KindArch::ARM);
1076
66
  bool useExternalReloc = useExternalRelocationTo(*ref.target());
1077
66
  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
1078
66
  int32_t displacement;
1079
66
  uint16_t value16;
1080
66
  uint32_t value32;
1081
66
  bool targetIsUndef = isa<UndefinedAtom>(ref.target());
1082
66
  switch (static_cast<ArmKind>(ref.kindValue())) {
1083
66
  case modeThumbCode:
1084
4
    thumbMode = true;
1085
4
    break;
1086
66
  case modeArmCode:
1087
0
    thumbMode = false;
1088
0
    break;
1089
66
  case modeData:
1090
0
    break;
1091
66
  case thumb_b22:
1092
5
  case thumb_bl22:
1093
5
    assert(thumbMode);
1094
5
    if (useExternalReloc)
1095
3
      displacement = (ref.addend() - (fixupAddress + 4));
1096
2
    else
1097
2
      displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
1098
5
    value32 = setDisplacementInThumbBranch(*loc32, fixupAddress,
1099
5
                                           displacement,
1100
5
                                           targetIsUndef || 
targetIsThumb2
);
1101
5
    *loc32 = value32;
1102
5
    break;
1103
7
  case thumb_movw:
1104
7
    assert(thumbMode);
1105
7
    if (useExternalReloc)
1106
2
      value16 = ref.addend() & 0xFFFF;
1107
5
    else
1108
5
      value16 = (targetAddress + ref.addend()) & 0xFFFF;
1109
7
    *loc32 = setWordFromThumbMov(*loc32, value16);
1110
7
    break;
1111
7
  case thumb_movt:
1112
7
    assert(thumbMode);
1113
7
    if (useExternalReloc)
1114
2
      value16 = ref.addend() >> 16;
1115
5
    else
1116
5
      value16 = (targetAddress + ref.addend()) >> 16;
1117
7
    *loc32 = setWordFromThumbMov(*loc32, value16);
1118
7
    break;
1119
5
  case thumb_movw_funcRel:
1120
5
    assert(thumbMode);
1121
5
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
1122
5
    *loc32 = setWordFromThumbMov(*loc32, value16);
1123
5
    break;
1124
5
  case thumb_movt_funcRel:
1125
5
    assert(thumbMode);
1126
5
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
1127
5
    *loc32 = setWordFromThumbMov(*loc32, value16);
1128
5
    break;
1129
5
  case arm_b24:
1130
5
  case arm_bl24:
1131
5
    assert(!thumbMode);
1132
5
    if (useExternalReloc)
1133
3
      displacement = (ref.addend() - (fixupAddress + 8));
1134
2
    else
1135
2
      displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
1136
5
    value32 = setDisplacementInArmBranch(*loc32, displacement,
1137
5
                                         targetIsThumb);
1138
5
    *loc32 = value32;
1139
5
    break;
1140
6
  case arm_movw:
1141
6
    assert(!thumbMode);
1142
6
    if (useExternalReloc)
1143
2
      value16 = ref.addend() & 0xFFFF;
1144
4
    else
1145
4
      value16 = (targetAddress + ref.addend()) & 0xFFFF;
1146
6
    *loc32 = setWordFromArmMov(*loc32, value16);
1147
6
    break;
1148
6
  case arm_movt:
1149
6
    assert(!thumbMode);
1150
6
    if (useExternalReloc)
1151
2
      value16 = ref.addend() >> 16;
1152
4
    else
1153
4
      value16 = (targetAddress + ref.addend()) >> 16;
1154
6
    *loc32 = setWordFromArmMov(*loc32, value16);
1155
6
    break;
1156
5
  case arm_movw_funcRel:
1157
4
    assert(!thumbMode);
1158
4
    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
1159
4
    *loc32 = setWordFromArmMov(*loc32, value16);
1160
4
    break;
1161
5
  case arm_movt_funcRel:
1162
4
    assert(!thumbMode);
1163
4
    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
1164
4
    *loc32 = setWordFromArmMov(*loc32, value16);
1165
4
    break;
1166
5
  case pointer32:
1167
4
    *loc32 = targetAddress + ref.addend();
1168
4
    break;
1169
5
  case delta32:
1170
4
    *loc32 = targetAddress - fixupAddress + ref.addend();
1171
4
    break;
1172
5
  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
66
  }
1180
66
}
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
66
                                   normalized::Relocations &relocs) {
1190
66
  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
1191
0
    return;
1192
66
  assert(ref.kindArch() == Reference::KindArch::ARM);
1193
66
  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
1194
66
  bool useExternalReloc = useExternalRelocationTo(*ref.target());
1195
66
  uint32_t targetAtomAddress;
1196
66
  uint32_t fromAtomAddress;
1197
66
  uint16_t other16;
1198
66
  switch (static_cast<ArmKind>(ref.kindValue())) {
1199
66
  case modeThumbCode:
1200
4
  case modeArmCode:
1201
4
  case modeData:
1202
4
    // Do nothing.
1203
4
    break;
1204
5
  case thumb_b22:
1205
5
  case thumb_bl22:
1206
5
    if (useExternalReloc) {
1207
3
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1208
3
                  ARM_THUMB_RELOC_BR22 | rExtern    | rPcRel | rLength4);
1209
3
    } else {
1210
2
      if (ref.addend() != 0)
1211
1
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1212
1
                  ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4);
1213
1
      else
1214
1
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1215
1
                  ARM_THUMB_RELOC_BR22 |              rPcRel | rLength4);
1216
2
    }
1217
5
    break;
1218
7
  case thumb_movw:
1219
7
    if (useExternalReloc) {
1220
2
      other16 = ref.addend() >> 16;
1221
2
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1222
2
                  ARM_RELOC_HALF | rExtern    | rLenThmbLo);
1223
2
      appendReloc(relocs, other16, 0, 0,
1224
2
                  ARM_RELOC_PAIR              | rLenThmbLo);
1225
5
    } else {
1226
5
      targetAtomAddress = addressForAtom(*ref.target());
1227
5
      if (ref.addend() != 0) {
1228
1
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1229
1
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1230
1
                  ARM_RELOC_HALF | rScattered | rLenThmbLo);
1231
1
        appendReloc(relocs, other16, 0, 0,
1232
1
                  ARM_RELOC_PAIR              | rLenThmbLo);
1233
4
      } else {
1234
4
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1235
4
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1236
4
                  ARM_RELOC_HALF              | rLenThmbLo);
1237
4
        appendReloc(relocs, other16, 0, 0,
1238
4
                  ARM_RELOC_PAIR              | rLenThmbLo);
1239
4
      }
1240
5
    }
1241
7
    break;
1242
7
  case thumb_movt:
1243
7
    if (useExternalReloc) {
1244
2
      other16 = ref.addend() & 0xFFFF;
1245
2
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1246
2
                  ARM_RELOC_HALF | rExtern    | rLenThmbHi);
1247
2
      appendReloc(relocs, other16, 0, 0,
1248
2
                  ARM_RELOC_PAIR              | rLenThmbHi);
1249
5
    } else {
1250
5
      targetAtomAddress = addressForAtom(*ref.target());
1251
5
      if (ref.addend() != 0) {
1252
1
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1253
1
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1254
1
                    ARM_RELOC_HALF | rScattered | rLenThmbHi);
1255
1
        appendReloc(relocs, other16, 0, 0,
1256
1
                    ARM_RELOC_PAIR              | rLenThmbHi);
1257
4
      } else {
1258
4
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1259
4
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1260
4
                    ARM_RELOC_HALF              | rLenThmbHi);
1261
4
        appendReloc(relocs, other16, 0, 0,
1262
4
                    ARM_RELOC_PAIR              | rLenThmbHi);
1263
4
      }
1264
5
    }
1265
7
    break;
1266
5
  case thumb_movw_funcRel:
1267
5
    fromAtomAddress = addressForAtom(atom);
1268
5
    targetAtomAddress = addressForAtom(*ref.target());
1269
5
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
1270
5
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1271
5
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbLo);
1272
5
    appendReloc(relocs, other16, 0, fromAtomAddress,
1273
5
                ARM_RELOC_PAIR          | rScattered | rLenThmbLo);
1274
5
    break;
1275
5
  case thumb_movt_funcRel:
1276
5
    fromAtomAddress = addressForAtom(atom);
1277
5
    targetAtomAddress = addressForAtom(*ref.target());
1278
5
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
1279
5
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1280
5
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbHi);
1281
5
    appendReloc(relocs, other16, 0, fromAtomAddress,
1282
5
                ARM_RELOC_PAIR          | rScattered | rLenThmbHi);
1283
5
    break;
1284
5
  case arm_b24:
1285
5
  case arm_bl24:
1286
5
    if (useExternalReloc) {
1287
3
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1288
3
                  ARM_RELOC_BR24 | rExtern    | rPcRel | rLength4);
1289
3
    } else {
1290
2
      if (ref.addend() != 0)
1291
1
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1292
1
                  ARM_RELOC_BR24 | rScattered | rPcRel | rLength4);
1293
1
      else
1294
1
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1295
1
                  ARM_RELOC_BR24 |              rPcRel | rLength4);
1296
2
    }
1297
5
    break;
1298
6
  case arm_movw:
1299
6
    if (useExternalReloc) {
1300
2
      other16 = ref.addend() >> 16;
1301
2
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1302
2
                  ARM_RELOC_HALF | rExtern    | rLenArmLo);
1303
2
      appendReloc(relocs, other16, 0, 0,
1304
2
                  ARM_RELOC_PAIR              | rLenArmLo);
1305
4
    } else {
1306
4
      targetAtomAddress = addressForAtom(*ref.target());
1307
4
      if (ref.addend() != 0) {
1308
1
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1309
1
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1310
1
                  ARM_RELOC_HALF | rScattered | rLenArmLo);
1311
1
        appendReloc(relocs, other16, 0, 0,
1312
1
                  ARM_RELOC_PAIR              | rLenArmLo);
1313
3
      } else {
1314
3
        other16 = (targetAtomAddress + ref.addend()) >> 16;
1315
3
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1316
3
                  ARM_RELOC_HALF              | rLenArmLo);
1317
3
        appendReloc(relocs, other16, 0, 0,
1318
3
                  ARM_RELOC_PAIR              | rLenArmLo);
1319
3
      }
1320
4
    }
1321
6
    break;
1322
6
  case arm_movt:
1323
6
    if (useExternalReloc) {
1324
2
      other16 = ref.addend() & 0xFFFF;
1325
2
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
1326
2
                  ARM_RELOC_HALF | rExtern    | rLenArmHi);
1327
2
      appendReloc(relocs, other16, 0, 0,
1328
2
                  ARM_RELOC_PAIR              | rLenArmHi);
1329
4
    } else {
1330
4
      targetAtomAddress = addressForAtom(*ref.target());
1331
4
      if (ref.addend() != 0) {
1332
1
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1333
1
        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1334
1
                  ARM_RELOC_HALF | rScattered | rLenArmHi);
1335
1
        appendReloc(relocs, other16, 0, 0,
1336
1
                  ARM_RELOC_PAIR              | rLenArmHi);
1337
3
      } else {
1338
3
        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
1339
3
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1340
3
                  ARM_RELOC_HALF              | rLenArmHi);
1341
3
        appendReloc(relocs, other16, 0, 0,
1342
3
                  ARM_RELOC_PAIR              | rLenArmHi);
1343
3
      }
1344
4
    }
1345
6
    break;
1346
5
  case arm_movw_funcRel:
1347
4
    fromAtomAddress = addressForAtom(atom);
1348
4
    targetAtomAddress = addressForAtom(*ref.target());
1349
4
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
1350
4
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1351
4
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmLo);
1352
4
    appendReloc(relocs, other16, 0, fromAtomAddress,
1353
4
                ARM_RELOC_PAIR          | rScattered | rLenArmLo);
1354
4
    break;
1355
5
  case arm_movt_funcRel:
1356
4
    fromAtomAddress = addressForAtom(atom);
1357
4
    targetAtomAddress = addressForAtom(*ref.target());
1358
4
    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
1359
4
    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
1360
4
                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmHi);
1361
4
    appendReloc(relocs, other16, 0, fromAtomAddress,
1362
4
                ARM_RELOC_PAIR          | rScattered | rLenArmHi);
1363
4
    break;
1364
5
  case pointer32:
1365
4
    if (useExternalReloc) {
1366
2
      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
1367
2
                ARM_RELOC_VANILLA |    rExtern     |  rLength4);
1368
2
    }
1369
2
    else {
1370
2
      if (ref.addend() != 0)
1371
1
        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1372
1
                ARM_RELOC_VANILLA |    rScattered  |  rLength4);
1373
1
      else
1374
1
        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
1375
1
                ARM_RELOC_VANILLA |                   rLength4);
1376
2
    }
1377
4
    break;
1378
5
  case delta32:
1379
4
    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
1380
4
              ARM_RELOC_SECTDIFF  |  rScattered    | rLength4);
1381
4
    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
1382
4
                                                           ref.offsetInAtom(),
1383
4
              ARM_RELOC_PAIR      |  rScattered    | rLength4);
1384
4
    break;
1385
5
  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
66
  }
1393
66
}
1394
1395
23
void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) {
1396
23
  if (atom.isThumb()) {
1397
11
    atom.addReference(Reference::KindNamespace::mach_o,
1398
11
                      Reference::KindArch::ARM, modeThumbCode, 0, &atom, 0);
1399
11
  }
1400
23
}
1401
1402
164
bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) {
1403
164
  for (const Reference *ref : atom) {
1404
156
    if (ref->offsetInAtom() != 0)
1405
65
      return false;
1406
91
    if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
1407
0
      continue;
1408
91
    assert(ref->kindArch() == Reference::KindArch::ARM);
1409
91
    if (ref->kindValue() == modeThumbCode)
1410
76
      return true;
1411
91
  }
1412
164
  
return false23
;
1413
164
}
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
8
  StringRef name() const override {
1432
8
    return _name;
1433
8
  }
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
8
  StringRef name() const override {
1477
8
    return _name;
1478
8
  }
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();
1512
4
  if (thumbToArm)
1513
2
    return new (file.allocator()) Thumb2ToArmShimAtom(file, targetName, target);
1514
2
  else
1515
2
    return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target);
1516
4
}
1517
1518
16
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
1519
16
  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
1520
16
}
1521
1522
} // namespace mach_o
1523
} // namespace lld