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