Coverage Report

Created: 2019-07-24 05:18

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