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