File: | lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp |
Warning: | line 438, column 9 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
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 "MCTargetDesc/ARMBaseInfo.h" | |||
11 | #include "MCTargetDesc/ARMFixupKinds.h" | |||
12 | #include "MCTargetDesc/ARMMCTargetDesc.h" | |||
13 | #include "llvm/ADT/Twine.h" | |||
14 | #include "llvm/BinaryFormat/MachO.h" | |||
15 | #include "llvm/MC/MCAsmLayout.h" | |||
16 | #include "llvm/MC/MCAssembler.h" | |||
17 | #include "llvm/MC/MCContext.h" | |||
18 | #include "llvm/MC/MCExpr.h" | |||
19 | #include "llvm/MC/MCFixup.h" | |||
20 | #include "llvm/MC/MCFixupKindInfo.h" | |||
21 | #include "llvm/MC/MCMachObjectWriter.h" | |||
22 | #include "llvm/MC/MCSection.h" | |||
23 | #include "llvm/MC/MCValue.h" | |||
24 | #include "llvm/Support/ErrorHandling.h" | |||
25 | #include "llvm/Support/ScopedPrinter.h" | |||
26 | ||||
27 | using namespace llvm; | |||
28 | ||||
29 | namespace { | |||
30 | class ARMMachObjectWriter : public MCMachObjectTargetWriter { | |||
31 | void RecordARMScatteredRelocation(MachObjectWriter *Writer, | |||
32 | const MCAssembler &Asm, | |||
33 | const MCAsmLayout &Layout, | |||
34 | const MCFragment *Fragment, | |||
35 | const MCFixup &Fixup, | |||
36 | MCValue Target, | |||
37 | unsigned Type, | |||
38 | unsigned Log2Size, | |||
39 | uint64_t &FixedValue); | |||
40 | void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, | |||
41 | const MCAssembler &Asm, | |||
42 | const MCAsmLayout &Layout, | |||
43 | const MCFragment *Fragment, | |||
44 | const MCFixup &Fixup, MCValue Target, | |||
45 | uint64_t &FixedValue); | |||
46 | ||||
47 | bool requiresExternRelocation(MachObjectWriter *Writer, | |||
48 | const MCAssembler &Asm, | |||
49 | const MCFragment &Fragment, unsigned RelocType, | |||
50 | const MCSymbol &S, uint64_t FixedValue); | |||
51 | ||||
52 | public: | |||
53 | ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) | |||
54 | : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} | |||
55 | ||||
56 | void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, | |||
57 | const MCAsmLayout &Layout, const MCFragment *Fragment, | |||
58 | const MCFixup &Fixup, MCValue Target, | |||
59 | uint64_t &FixedValue) override; | |||
60 | }; | |||
61 | } | |||
62 | ||||
63 | static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, | |||
64 | unsigned &Log2Size) { | |||
65 | RelocType = unsigned(MachO::ARM_RELOC_VANILLA); | |||
66 | Log2Size = ~0U; | |||
67 | ||||
68 | switch (Kind) { | |||
69 | default: | |||
70 | return false; | |||
71 | ||||
72 | case FK_Data_1: | |||
73 | Log2Size = llvm::Log2_32(1); | |||
74 | return true; | |||
75 | case FK_Data_2: | |||
76 | Log2Size = llvm::Log2_32(2); | |||
77 | return true; | |||
78 | case FK_Data_4: | |||
79 | Log2Size = llvm::Log2_32(4); | |||
80 | return true; | |||
81 | case FK_Data_8: | |||
82 | Log2Size = llvm::Log2_32(8); | |||
83 | return true; | |||
84 | ||||
85 | // These fixups are expected to always be resolvable at assembly time and | |||
86 | // have no relocations supported. | |||
87 | case ARM::fixup_arm_ldst_pcrel_12: | |||
88 | case ARM::fixup_arm_pcrel_10: | |||
89 | case ARM::fixup_arm_adr_pcrel_12: | |||
90 | case ARM::fixup_arm_thumb_br: | |||
91 | return false; | |||
92 | ||||
93 | // Handle 24-bit branch kinds. | |||
94 | case ARM::fixup_arm_condbranch: | |||
95 | case ARM::fixup_arm_uncondbranch: | |||
96 | case ARM::fixup_arm_uncondbl: | |||
97 | case ARM::fixup_arm_condbl: | |||
98 | case ARM::fixup_arm_blx: | |||
99 | RelocType = unsigned(MachO::ARM_RELOC_BR24); | |||
100 | // Report as 'long', even though that is not quite accurate. | |||
101 | Log2Size = llvm::Log2_32(4); | |||
102 | return true; | |||
103 | ||||
104 | case ARM::fixup_t2_uncondbranch: | |||
105 | case ARM::fixup_arm_thumb_bl: | |||
106 | case ARM::fixup_arm_thumb_blx: | |||
107 | RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22); | |||
108 | Log2Size = llvm::Log2_32(4); | |||
109 | return true; | |||
110 | ||||
111 | // For movw/movt r_type relocations they always have a pair following them and | |||
112 | // the r_length bits are used differently. The encoding of the r_length is as | |||
113 | // follows: | |||
114 | // low bit of r_length: | |||
115 | // 0 - :lower16: for movw instructions | |||
116 | // 1 - :upper16: for movt instructions | |||
117 | // high bit of r_length: | |||
118 | // 0 - arm instructions | |||
119 | // 1 - thumb instructions | |||
120 | case ARM::fixup_arm_movt_hi16: | |||
121 | RelocType = unsigned(MachO::ARM_RELOC_HALF); | |||
122 | Log2Size = 1; | |||
123 | return true; | |||
124 | case ARM::fixup_t2_movt_hi16: | |||
125 | RelocType = unsigned(MachO::ARM_RELOC_HALF); | |||
126 | Log2Size = 3; | |||
127 | return true; | |||
128 | ||||
129 | case ARM::fixup_arm_movw_lo16: | |||
130 | RelocType = unsigned(MachO::ARM_RELOC_HALF); | |||
131 | Log2Size = 0; | |||
132 | return true; | |||
133 | case ARM::fixup_t2_movw_lo16: | |||
134 | RelocType = unsigned(MachO::ARM_RELOC_HALF); | |||
135 | Log2Size = 2; | |||
136 | return true; | |||
137 | } | |||
138 | } | |||
139 | ||||
140 | void ARMMachObjectWriter:: | |||
141 | RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, | |||
142 | const MCAssembler &Asm, | |||
143 | const MCAsmLayout &Layout, | |||
144 | const MCFragment *Fragment, | |||
145 | const MCFixup &Fixup, | |||
146 | MCValue Target, | |||
147 | uint64_t &FixedValue) { | |||
148 | uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); | |||
149 | ||||
150 | if (FixupOffset & 0xff000000) { | |||
151 | Asm.getContext().reportError(Fixup.getLoc(), | |||
152 | "can not encode offset '0x" + | |||
153 | to_hexString(FixupOffset) + | |||
154 | "' in resulting scattered relocation."); | |||
155 | return; | |||
156 | } | |||
157 | ||||
158 | unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); | |||
159 | unsigned Type = MachO::ARM_RELOC_HALF; | |||
160 | ||||
161 | // See <reloc.h>. | |||
162 | const MCSymbol *A = &Target.getSymA()->getSymbol(); | |||
163 | ||||
164 | if (!A->getFragment()) { | |||
165 | Asm.getContext().reportError(Fixup.getLoc(), | |||
166 | "symbol '" + A->getName() + | |||
167 | "' can not be undefined in a subtraction expression"); | |||
168 | return; | |||
169 | } | |||
170 | ||||
171 | uint32_t Value = Writer->getSymbolAddress(*A, Layout); | |||
172 | uint32_t Value2 = 0; | |||
173 | uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent()); | |||
174 | FixedValue += SecAddr; | |||
175 | ||||
176 | if (const MCSymbolRefExpr *B = Target.getSymB()) { | |||
177 | const MCSymbol *SB = &B->getSymbol(); | |||
178 | ||||
179 | if (!SB->getFragment()) { | |||
180 | Asm.getContext().reportError(Fixup.getLoc(), | |||
181 | "symbol '" + B->getSymbol().getName() + | |||
182 | "' can not be undefined in a subtraction expression"); | |||
183 | return; | |||
184 | } | |||
185 | ||||
186 | // Select the appropriate difference relocation type. | |||
187 | Type = MachO::ARM_RELOC_HALF_SECTDIFF; | |||
188 | Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout); | |||
189 | FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent()); | |||
190 | } | |||
191 | ||||
192 | // Relocations are written out in reverse order, so the PAIR comes first. | |||
193 | // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: | |||
194 | // | |||
195 | // For these two r_type relocations they always have a pair following them and | |||
196 | // the r_length bits are used differently. The encoding of the r_length is as | |||
197 | // follows: | |||
198 | // low bit of r_length: | |||
199 | // 0 - :lower16: for movw instructions | |||
200 | // 1 - :upper16: for movt instructions | |||
201 | // high bit of r_length: | |||
202 | // 0 - arm instructions | |||
203 | // 1 - thumb instructions | |||
204 | // the other half of the relocated expression is in the following pair | |||
205 | // relocation entry in the low 16 bits of r_address field. | |||
206 | unsigned ThumbBit = 0; | |||
207 | unsigned MovtBit = 0; | |||
208 | switch ((unsigned)Fixup.getKind()) { | |||
209 | default: break; | |||
210 | case ARM::fixup_arm_movt_hi16: | |||
211 | MovtBit = 1; | |||
212 | // The thumb bit shouldn't be set in the 'other-half' bit of the | |||
213 | // relocation, but it will be set in FixedValue if the base symbol | |||
214 | // is a thumb function. Clear it out here. | |||
215 | if (Asm.isThumbFunc(A)) | |||
216 | FixedValue &= 0xfffffffe; | |||
217 | break; | |||
218 | case ARM::fixup_t2_movt_hi16: | |||
219 | if (Asm.isThumbFunc(A)) | |||
220 | FixedValue &= 0xfffffffe; | |||
221 | MovtBit = 1; | |||
222 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
223 | case ARM::fixup_t2_movw_lo16: | |||
224 | ThumbBit = 1; | |||
225 | break; | |||
226 | } | |||
227 | ||||
228 | if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { | |||
229 | uint32_t OtherHalf = MovtBit | |||
230 | ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); | |||
231 | ||||
232 | MachO::any_relocation_info MRE; | |||
233 | MRE.r_word0 = ((OtherHalf << 0) | | |||
234 | (MachO::ARM_RELOC_PAIR << 24) | | |||
235 | (MovtBit << 28) | | |||
236 | (ThumbBit << 29) | | |||
237 | (IsPCRel << 30) | | |||
238 | MachO::R_SCATTERED); | |||
239 | MRE.r_word1 = Value2; | |||
240 | Writer->addRelocation(nullptr, Fragment->getParent(), MRE); | |||
241 | } | |||
242 | ||||
243 | MachO::any_relocation_info MRE; | |||
244 | MRE.r_word0 = ((FixupOffset << 0) | | |||
245 | (Type << 24) | | |||
246 | (MovtBit << 28) | | |||
247 | (ThumbBit << 29) | | |||
248 | (IsPCRel << 30) | | |||
249 | MachO::R_SCATTERED); | |||
250 | MRE.r_word1 = Value; | |||
251 | Writer->addRelocation(nullptr, Fragment->getParent(), MRE); | |||
252 | } | |||
253 | ||||
254 | void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, | |||
255 | const MCAssembler &Asm, | |||
256 | const MCAsmLayout &Layout, | |||
257 | const MCFragment *Fragment, | |||
258 | const MCFixup &Fixup, | |||
259 | MCValue Target, | |||
260 | unsigned Type, | |||
261 | unsigned Log2Size, | |||
262 | uint64_t &FixedValue) { | |||
263 | uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); | |||
264 | ||||
265 | if (FixupOffset & 0xff000000) { | |||
266 | Asm.getContext().reportError(Fixup.getLoc(), | |||
267 | "can not encode offset '0x" + | |||
268 | to_hexString(FixupOffset) + | |||
269 | "' in resulting scattered relocation."); | |||
270 | return; | |||
271 | } | |||
272 | ||||
273 | unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); | |||
274 | ||||
275 | // See <reloc.h>. | |||
276 | const MCSymbol *A = &Target.getSymA()->getSymbol(); | |||
277 | ||||
278 | if (!A->getFragment()) { | |||
279 | Asm.getContext().reportError(Fixup.getLoc(), | |||
280 | "symbol '" + A->getName() + | |||
281 | "' can not be undefined in a subtraction expression"); | |||
282 | return; | |||
283 | } | |||
284 | ||||
285 | uint32_t Value = Writer->getSymbolAddress(*A, Layout); | |||
286 | uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent()); | |||
287 | FixedValue += SecAddr; | |||
288 | uint32_t Value2 = 0; | |||
289 | ||||
290 | if (const MCSymbolRefExpr *B = Target.getSymB()) { | |||
291 | assert(Type == MachO::ARM_RELOC_VANILLA && "invalid reloc for 2 symbols")((Type == MachO::ARM_RELOC_VANILLA && "invalid reloc for 2 symbols" ) ? static_cast<void> (0) : __assert_fail ("Type == MachO::ARM_RELOC_VANILLA && \"invalid reloc for 2 symbols\"" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp" , 291, __PRETTY_FUNCTION__)); | |||
292 | const MCSymbol *SB = &B->getSymbol(); | |||
293 | ||||
294 | if (!SB->getFragment()) { | |||
295 | Asm.getContext().reportError(Fixup.getLoc(), | |||
296 | "symbol '" + B->getSymbol().getName() + | |||
297 | "' can not be undefined in a subtraction expression"); | |||
298 | return; | |||
299 | } | |||
300 | ||||
301 | // Select the appropriate difference relocation type. | |||
302 | Type = MachO::ARM_RELOC_SECTDIFF; | |||
303 | Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout); | |||
304 | FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent()); | |||
305 | } | |||
306 | ||||
307 | // Relocations are written out in reverse order, so the PAIR comes first. | |||
308 | if (Type == MachO::ARM_RELOC_SECTDIFF || | |||
309 | Type == MachO::ARM_RELOC_LOCAL_SECTDIFF) { | |||
310 | MachO::any_relocation_info MRE; | |||
311 | MRE.r_word0 = ((0 << 0) | | |||
312 | (MachO::ARM_RELOC_PAIR << 24) | | |||
313 | (Log2Size << 28) | | |||
314 | (IsPCRel << 30) | | |||
315 | MachO::R_SCATTERED); | |||
316 | MRE.r_word1 = Value2; | |||
317 | Writer->addRelocation(nullptr, Fragment->getParent(), MRE); | |||
318 | } | |||
319 | ||||
320 | MachO::any_relocation_info MRE; | |||
321 | MRE.r_word0 = ((FixupOffset << 0) | | |||
322 | (Type << 24) | | |||
323 | (Log2Size << 28) | | |||
324 | (IsPCRel << 30) | | |||
325 | MachO::R_SCATTERED); | |||
326 | MRE.r_word1 = Value; | |||
327 | Writer->addRelocation(nullptr, Fragment->getParent(), MRE); | |||
328 | } | |||
329 | ||||
330 | bool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer, | |||
331 | const MCAssembler &Asm, | |||
332 | const MCFragment &Fragment, | |||
333 | unsigned RelocType, | |||
334 | const MCSymbol &S, | |||
335 | uint64_t FixedValue) { | |||
336 | // Most cases can be identified purely from the symbol. | |||
337 | if (Writer->doesSymbolRequireExternRelocation(S)) | |||
338 | return true; | |||
339 | int64_t Value = (int64_t)FixedValue; // The displacement is signed. | |||
340 | int64_t Range; | |||
341 | switch (RelocType) { | |||
342 | default: | |||
343 | return false; | |||
344 | case MachO::ARM_RELOC_BR24: | |||
345 | // An ARM call might be to a Thumb function, in which case the offset may | |||
346 | // not be encodable in the instruction and we must use an external | |||
347 | // relocation that explicitly mentions the function. Not a problem if it's | |||
348 | // to a temporary "Lwhatever" symbol though, and in fact trying to use an | |||
349 | // external relocation there causes more issues. | |||
350 | if (!S.isTemporary()) | |||
351 | return true; | |||
352 | ||||
353 | // PC pre-adjustment of 8 for these instructions. | |||
354 | Value -= 8; | |||
355 | // ARM BL/BLX has a 25-bit offset. | |||
356 | Range = 0x1ffffff; | |||
357 | break; | |||
358 | case MachO::ARM_THUMB_RELOC_BR22: | |||
359 | // PC pre-adjustment of 4 for these instructions. | |||
360 | Value -= 4; | |||
361 | // Thumb BL/BLX has a 24-bit offset. | |||
362 | Range = 0xffffff; | |||
363 | } | |||
364 | // BL/BLX also use external relocations when an internal relocation | |||
365 | // would result in the target being out of range. This gives the linker | |||
366 | // enough information to generate a branch island. | |||
367 | Value += Writer->getSectionAddress(&S.getSection()); | |||
368 | Value -= Writer->getSectionAddress(Fragment.getParent()); | |||
369 | // If the resultant value would be out of range for an internal relocation, | |||
370 | // use an external instead. | |||
371 | if (Value > Range || Value < -(Range + 1)) | |||
372 | return true; | |||
373 | return false; | |||
374 | } | |||
375 | ||||
376 | void ARMMachObjectWriter::recordRelocation(MachObjectWriter *Writer, | |||
377 | MCAssembler &Asm, | |||
378 | const MCAsmLayout &Layout, | |||
379 | const MCFragment *Fragment, | |||
380 | const MCFixup &Fixup, MCValue Target, | |||
381 | uint64_t &FixedValue) { | |||
382 | unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); | |||
383 | unsigned Log2Size; | |||
384 | unsigned RelocType = MachO::ARM_RELOC_VANILLA; | |||
385 | if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) { | |||
| ||||
386 | // If we failed to get fixup kind info, it's because there's no legal | |||
387 | // relocation type for the fixup kind. This happens when it's a fixup that's | |||
388 | // expected to always be resolvable at assembly time and not have any | |||
389 | // relocations needed. | |||
390 | Asm.getContext().reportError(Fixup.getLoc(), | |||
391 | "unsupported relocation on symbol"); | |||
392 | return; | |||
393 | } | |||
394 | ||||
395 | // If this is a difference or a defined symbol plus an offset, then we need a | |||
396 | // scattered relocation entry. Differences always require scattered | |||
397 | // relocations. | |||
398 | if (Target.getSymB()) { | |||
399 | if (RelocType == MachO::ARM_RELOC_HALF) | |||
400 | return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment, | |||
401 | Fixup, Target, FixedValue); | |||
402 | return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, | |||
403 | Target, RelocType, Log2Size, | |||
404 | FixedValue); | |||
405 | } | |||
406 | ||||
407 | // Get the symbol data, if any. | |||
408 | const MCSymbol *A = nullptr; | |||
409 | if (Target.getSymA()) | |||
410 | A = &Target.getSymA()->getSymbol(); | |||
411 | ||||
412 | // FIXME: For other platforms, we need to use scattered relocations for | |||
413 | // internal relocations with offsets. If this is an internal relocation with | |||
414 | // an offset, it also needs a scattered relocation entry. | |||
415 | // | |||
416 | // Is this right for ARM? | |||
417 | uint32_t Offset = Target.getConstant(); | |||
418 | if (IsPCRel && RelocType == MachO::ARM_RELOC_VANILLA) | |||
419 | Offset += 1 << Log2Size; | |||
420 | if (Offset && A && !Writer->doesSymbolRequireExternRelocation(*A) && | |||
421 | RelocType != MachO::ARM_RELOC_HALF) | |||
422 | return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, | |||
423 | Target, RelocType, Log2Size, | |||
424 | FixedValue); | |||
425 | ||||
426 | // See <reloc.h>. | |||
427 | uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); | |||
428 | unsigned Index = 0; | |||
429 | unsigned Type = 0; | |||
430 | const MCSymbol *RelSymbol = nullptr; | |||
431 | ||||
432 | if (Target.isAbsolute()) { // constant | |||
433 | // FIXME! | |||
434 | report_fatal_error("FIXME: relocations to absolute targets " | |||
435 | "not yet implemented"); | |||
436 | } else { | |||
437 | // Resolve constant variables. | |||
438 | if (A->isVariable()) { | |||
| ||||
439 | int64_t Res; | |||
440 | if (A->getVariableValue()->evaluateAsAbsolute( | |||
441 | Res, Layout, Writer->getSectionAddressMap())) { | |||
442 | FixedValue = Res; | |||
443 | return; | |||
444 | } | |||
445 | } | |||
446 | ||||
447 | // Check whether we need an external or internal relocation. | |||
448 | if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, *A, | |||
449 | FixedValue)) { | |||
450 | RelSymbol = A; | |||
451 | ||||
452 | // For external relocations, make sure to offset the fixup value to | |||
453 | // compensate for the addend of the symbol address, if it was | |||
454 | // undefined. This occurs with weak definitions, for example. | |||
455 | if (!A->isUndefined()) | |||
456 | FixedValue -= Layout.getSymbolOffset(*A); | |||
457 | } else { | |||
458 | // The index is the section ordinal (1-based). | |||
459 | const MCSection &Sec = A->getSection(); | |||
460 | Index = Sec.getOrdinal() + 1; | |||
461 | FixedValue += Writer->getSectionAddress(&Sec); | |||
462 | } | |||
463 | if (IsPCRel) | |||
464 | FixedValue -= Writer->getSectionAddress(Fragment->getParent()); | |||
465 | ||||
466 | // The type is determined by the fixup kind. | |||
467 | Type = RelocType; | |||
468 | } | |||
469 | ||||
470 | // struct relocation_info (8 bytes) | |||
471 | MachO::any_relocation_info MRE; | |||
472 | MRE.r_word0 = FixupOffset; | |||
473 | MRE.r_word1 = | |||
474 | (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28); | |||
475 | ||||
476 | // Even when it's not a scattered relocation, movw/movt always uses | |||
477 | // a PAIR relocation. | |||
478 | if (Type == MachO::ARM_RELOC_HALF) { | |||
479 | // The entire addend is needed to correctly apply a relocation. One half is | |||
480 | // extracted from the instruction itself, the other comes from this | |||
481 | // PAIR. I.e. it's correct that we insert the high bits of the addend in the | |||
482 | // MOVW case here. relocation entries. | |||
483 | uint32_t Value = 0; | |||
484 | switch ((unsigned)Fixup.getKind()) { | |||
485 | default: break; | |||
486 | case ARM::fixup_arm_movw_lo16: | |||
487 | case ARM::fixup_t2_movw_lo16: | |||
488 | Value = (FixedValue >> 16) & 0xffff; | |||
489 | break; | |||
490 | case ARM::fixup_arm_movt_hi16: | |||
491 | case ARM::fixup_t2_movt_hi16: | |||
492 | Value = FixedValue & 0xffff; | |||
493 | break; | |||
494 | } | |||
495 | MachO::any_relocation_info MREPair; | |||
496 | MREPair.r_word0 = Value; | |||
497 | MREPair.r_word1 = ((0xffffff << 0) | | |||
498 | (Log2Size << 25) | | |||
499 | (MachO::ARM_RELOC_PAIR << 28)); | |||
500 | ||||
501 | Writer->addRelocation(nullptr, Fragment->getParent(), MREPair); | |||
502 | } | |||
503 | ||||
504 | Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE); | |||
505 | } | |||
506 | ||||
507 | std::unique_ptr<MCObjectTargetWriter> | |||
508 | llvm::createARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, | |||
509 | uint32_t CPUSubtype) { | |||
510 | return llvm::make_unique<ARMMachObjectWriter>(Is64Bit, CPUType, CPUSubtype); | |||
511 | } |