blob: 7da500390ed1307aa4da0b81a7fc288d91cae2b2 [file] [log] [blame]
Jim Grosbach2354f872011-06-22 20:14:52 +00001//===-- 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
Chandler Carruthed0881b2012-12-03 16:50:05 +000010#include "MCTargetDesc/ARMMCTargetDesc.h"
Evan Chengad5f4852011-07-23 00:00:19 +000011#include "MCTargetDesc/ARMBaseInfo.h"
12#include "MCTargetDesc/ARMFixupKinds.h"
Jim Grosbach28fcafb2011-06-24 23:44:37 +000013#include "llvm/ADT/Twine.h"
Jim Grosbach28fcafb2011-06-24 23:44:37 +000014#include "llvm/MC/MCAsmLayout.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000015#include "llvm/MC/MCAssembler.h"
Jim Grosbach5e5eabb2012-01-26 23:20:15 +000016#include "llvm/MC/MCContext.h"
Jim Grosbach28fcafb2011-06-24 23:44:37 +000017#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCFixup.h"
19#include "llvm/MC/MCFixupKindInfo.h"
Jim Grosbachae913222011-11-29 01:15:25 +000020#include "llvm/MC/MCMachOSymbolFlags.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCMachObjectWriter.h"
Jim Grosbach28fcafb2011-06-24 23:44:37 +000022#include "llvm/MC/MCValue.h"
Jim Grosbach28fcafb2011-06-24 23:44:37 +000023#include "llvm/Support/ErrorHandling.h"
Charles Davis8bdfafd2013-09-01 04:28:48 +000024#include "llvm/Support/MachO.h"
Jim Grosbach2354f872011-06-22 20:14:52 +000025using namespace llvm;
26
27namespace {
28class ARMMachObjectWriter : public MCMachObjectTargetWriter {
Jim Grosbach28fcafb2011-06-24 23:44:37 +000029 void RecordARMScatteredRelocation(MachObjectWriter *Writer,
30 const MCAssembler &Asm,
31 const MCAsmLayout &Layout,
32 const MCFragment *Fragment,
33 const MCFixup &Fixup,
34 MCValue Target,
Tim Northover1bc367a2014-07-04 10:58:05 +000035 unsigned Type,
Jim Grosbach28fcafb2011-06-24 23:44:37 +000036 unsigned Log2Size,
37 uint64_t &FixedValue);
Jim Grosbach997614f2012-03-20 17:25:45 +000038 void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
39 const MCAssembler &Asm,
40 const MCAsmLayout &Layout,
41 const MCFragment *Fragment,
42 const MCFixup &Fixup, MCValue Target,
43 uint64_t &FixedValue);
Jim Grosbach28fcafb2011-06-24 23:44:37 +000044
Jim Grosbachdf8ed712012-09-25 18:07:17 +000045 bool requiresExternRelocation(MachObjectWriter *Writer,
46 const MCAssembler &Asm,
47 const MCFragment &Fragment,
48 unsigned RelocType, const MCSymbolData *SD,
49 uint64_t FixedValue);
50
Jim Grosbach2354f872011-06-22 20:14:52 +000051public:
52 ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType,
53 uint32_t CPUSubtype)
54 : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
55 /*UseAggressiveSymbolFolding=*/true) {}
Jim Grosbach28fcafb2011-06-24 23:44:37 +000056
57 void RecordRelocation(MachObjectWriter *Writer,
58 const MCAssembler &Asm, const MCAsmLayout &Layout,
59 const MCFragment *Fragment, const MCFixup &Fixup,
Craig Topperca7e3e52014-03-10 03:19:03 +000060 MCValue Target, uint64_t &FixedValue) override;
Jim Grosbach2354f872011-06-22 20:14:52 +000061};
62}
63
Jim Grosbach28fcafb2011-06-24 23:44:37 +000064static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
65 unsigned &Log2Size) {
Charles Davis8bdfafd2013-09-01 04:28:48 +000066 RelocType = unsigned(MachO::ARM_RELOC_VANILLA);
Jim Grosbach28fcafb2011-06-24 23:44:37 +000067 Log2Size = ~0U;
68
69 switch (Kind) {
70 default:
71 return false;
72
73 case FK_Data_1:
74 Log2Size = llvm::Log2_32(1);
75 return true;
76 case FK_Data_2:
77 Log2Size = llvm::Log2_32(2);
78 return true;
79 case FK_Data_4:
80 Log2Size = llvm::Log2_32(4);
81 return true;
82 case FK_Data_8:
83 Log2Size = llvm::Log2_32(8);
84 return true;
85
Kevin Enderby651898c2013-12-13 22:46:54 +000086 // These fixups are expected to always be resolvable at assembly time and
87 // have no relocations supported.
Jim Grosbach28fcafb2011-06-24 23:44:37 +000088 case ARM::fixup_arm_ldst_pcrel_12:
89 case ARM::fixup_arm_pcrel_10:
90 case ARM::fixup_arm_adr_pcrel_12:
Kevin Enderby651898c2013-12-13 22:46:54 +000091 return false;
92
93 // Handle 24-bit branch kinds.
Jim Grosbach28fcafb2011-06-24 23:44:37 +000094 case ARM::fixup_arm_condbranch:
95 case ARM::fixup_arm_uncondbranch:
James Molloyfb5cd602012-03-30 09:15:32 +000096 case ARM::fixup_arm_uncondbl:
97 case ARM::fixup_arm_condbl:
Jim Grosbach7b811d32012-02-27 21:36:23 +000098 case ARM::fixup_arm_blx:
Charles Davis8bdfafd2013-09-01 04:28:48 +000099 RelocType = unsigned(MachO::ARM_RELOC_BR24);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000100 // Report as 'long', even though that is not quite accurate.
101 Log2Size = llvm::Log2_32(4);
102 return true;
103
104 // Handle Thumb branches.
105 case ARM::fixup_arm_thumb_br:
Charles Davis8bdfafd2013-09-01 04:28:48 +0000106 RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000107 Log2Size = llvm::Log2_32(2);
108 return true;
109
110 case ARM::fixup_t2_uncondbranch:
111 case ARM::fixup_arm_thumb_bl:
112 case ARM::fixup_arm_thumb_blx:
Charles Davis8bdfafd2013-09-01 04:28:48 +0000113 RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000114 Log2Size = llvm::Log2_32(4);
115 return true;
116
Jim Grosbach997614f2012-03-20 17:25:45 +0000117 // For movw/movt r_type relocations they always have a pair following them and
118 // the r_length bits are used differently. The encoding of the r_length is as
119 // follows:
120 // low bit of r_length:
121 // 0 - :lower16: for movw instructions
122 // 1 - :upper16: for movt instructions
123 // high bit of r_length:
124 // 0 - arm instructions
125 // 1 - thumb instructions
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000126 case ARM::fixup_arm_movt_hi16:
Charles Davis8bdfafd2013-09-01 04:28:48 +0000127 RelocType = unsigned(MachO::ARM_RELOC_HALF);
Jim Grosbach997614f2012-03-20 17:25:45 +0000128 Log2Size = 1;
129 return true;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000130 case ARM::fixup_t2_movt_hi16:
Charles Davis8bdfafd2013-09-01 04:28:48 +0000131 RelocType = unsigned(MachO::ARM_RELOC_HALF);
Jim Grosbach997614f2012-03-20 17:25:45 +0000132 Log2Size = 3;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000133 return true;
134
135 case ARM::fixup_arm_movw_lo16:
Charles Davis8bdfafd2013-09-01 04:28:48 +0000136 RelocType = unsigned(MachO::ARM_RELOC_HALF);
Jim Grosbach997614f2012-03-20 17:25:45 +0000137 Log2Size = 0;
138 return true;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000139 case ARM::fixup_t2_movw_lo16:
Charles Davis8bdfafd2013-09-01 04:28:48 +0000140 RelocType = unsigned(MachO::ARM_RELOC_HALF);
Jim Grosbach997614f2012-03-20 17:25:45 +0000141 Log2Size = 2;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000142 return true;
143 }
144}
145
146void ARMMachObjectWriter::
Jim Grosbach997614f2012-03-20 17:25:45 +0000147RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
148 const MCAssembler &Asm,
149 const MCAsmLayout &Layout,
150 const MCFragment *Fragment,
151 const MCFixup &Fixup,
152 MCValue Target,
153 uint64_t &FixedValue) {
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000154 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
155 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
Charles Davis8bdfafd2013-09-01 04:28:48 +0000156 unsigned Type = MachO::ARM_RELOC_HALF;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000157
158 // See <reloc.h>.
159 const MCSymbol *A = &Target.getSymA()->getSymbol();
David Blaikie908f4d42014-04-24 16:59:40 +0000160 const MCSymbolData *A_SD = &Asm.getSymbolData(*A);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000161
162 if (!A_SD->getFragment())
Jim Grosbach20275a82012-01-27 00:37:12 +0000163 Asm.getContext().FatalError(Fixup.getLoc(),
164 "symbol '" + A->getName() +
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000165 "' can not be undefined in a subtraction expression");
166
167 uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
168 uint32_t Value2 = 0;
169 uint64_t SecAddr =
170 Writer->getSectionAddress(A_SD->getFragment()->getParent());
171 FixedValue += SecAddr;
172
173 if (const MCSymbolRefExpr *B = Target.getSymB()) {
David Blaikie908f4d42014-04-24 16:59:40 +0000174 const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000175
176 if (!B_SD->getFragment())
Jim Grosbach20275a82012-01-27 00:37:12 +0000177 Asm.getContext().FatalError(Fixup.getLoc(),
178 "symbol '" + B->getSymbol().getName() +
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000179 "' can not be undefined in a subtraction expression");
180
181 // Select the appropriate difference relocation type.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000182 Type = MachO::ARM_RELOC_HALF_SECTDIFF;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000183 Value2 = Writer->getSymbolAddress(B_SD, Layout);
184 FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
185 }
186
187 // Relocations are written out in reverse order, so the PAIR comes first.
188 // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
189 //
190 // For these two r_type relocations they always have a pair following them and
191 // the r_length bits are used differently. The encoding of the r_length is as
192 // follows:
193 // low bit of r_length:
194 // 0 - :lower16: for movw instructions
195 // 1 - :upper16: for movt instructions
196 // high bit of r_length:
197 // 0 - arm instructions
198 // 1 - thumb instructions
199 // the other half of the relocated expression is in the following pair
Sylvestre Ledru35521e22012-07-23 08:51:15 +0000200 // relocation entry in the low 16 bits of r_address field.
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000201 unsigned ThumbBit = 0;
202 unsigned MovtBit = 0;
203 switch ((unsigned)Fixup.getKind()) {
204 default: break;
205 case ARM::fixup_arm_movt_hi16:
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000206 MovtBit = 1;
Jim Grosbachae913222011-11-29 01:15:25 +0000207 // The thumb bit shouldn't be set in the 'other-half' bit of the
208 // relocation, but it will be set in FixedValue if the base symbol
209 // is a thumb function. Clear it out here.
Rafael Espindolab60c8292014-04-29 12:46:50 +0000210 if (Asm.isThumbFunc(A))
Jim Grosbachae913222011-11-29 01:15:25 +0000211 FixedValue &= 0xfffffffe;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000212 break;
213 case ARM::fixup_t2_movt_hi16:
Rafael Espindolab60c8292014-04-29 12:46:50 +0000214 if (Asm.isThumbFunc(A))
Jim Grosbachae913222011-11-29 01:15:25 +0000215 FixedValue &= 0xfffffffe;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000216 MovtBit = 1;
217 // Fallthrough
218 case ARM::fixup_t2_movw_lo16:
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000219 ThumbBit = 1;
220 break;
221 }
222
Charles Davis8bdfafd2013-09-01 04:28:48 +0000223 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000224 uint32_t OtherHalf = MovtBit
225 ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
226
Charles Davis8bdfafd2013-09-01 04:28:48 +0000227 MachO::any_relocation_info MRE;
228 MRE.r_word0 = ((OtherHalf << 0) |
229 (MachO::ARM_RELOC_PAIR << 24) |
230 (MovtBit << 28) |
231 (ThumbBit << 29) |
232 (IsPCRel << 30) |
233 MachO::R_SCATTERED);
234 MRE.r_word1 = Value2;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000235 Writer->addRelocation(Fragment->getParent(), MRE);
236 }
237
Charles Davis8bdfafd2013-09-01 04:28:48 +0000238 MachO::any_relocation_info MRE;
239 MRE.r_word0 = ((FixupOffset << 0) |
240 (Type << 24) |
241 (MovtBit << 28) |
242 (ThumbBit << 29) |
243 (IsPCRel << 30) |
244 MachO::R_SCATTERED);
245 MRE.r_word1 = Value;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000246 Writer->addRelocation(Fragment->getParent(), MRE);
247}
248
249void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
250 const MCAssembler &Asm,
251 const MCAsmLayout &Layout,
252 const MCFragment *Fragment,
253 const MCFixup &Fixup,
254 MCValue Target,
Tim Northover1bc367a2014-07-04 10:58:05 +0000255 unsigned Type,
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000256 unsigned Log2Size,
257 uint64_t &FixedValue) {
258 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
259 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000260
261 // See <reloc.h>.
262 const MCSymbol *A = &Target.getSymA()->getSymbol();
David Blaikie908f4d42014-04-24 16:59:40 +0000263 const MCSymbolData *A_SD = &Asm.getSymbolData(*A);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000264
265 if (!A_SD->getFragment())
Jim Grosbach20275a82012-01-27 00:37:12 +0000266 Asm.getContext().FatalError(Fixup.getLoc(),
267 "symbol '" + A->getName() +
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000268 "' can not be undefined in a subtraction expression");
269
270 uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
271 uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
272 FixedValue += SecAddr;
273 uint32_t Value2 = 0;
274
275 if (const MCSymbolRefExpr *B = Target.getSymB()) {
Tim Northover1bc367a2014-07-04 10:58:05 +0000276 assert(Type == MachO::ARM_RELOC_VANILLA && "invalid reloc for 2 symbols");
David Blaikie908f4d42014-04-24 16:59:40 +0000277 const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000278
279 if (!B_SD->getFragment())
Jim Grosbach20275a82012-01-27 00:37:12 +0000280 Asm.getContext().FatalError(Fixup.getLoc(),
281 "symbol '" + B->getSymbol().getName() +
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000282 "' can not be undefined in a subtraction expression");
283
284 // Select the appropriate difference relocation type.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000285 Type = MachO::ARM_RELOC_SECTDIFF;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000286 Value2 = Writer->getSymbolAddress(B_SD, Layout);
287 FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
288 }
289
290 // Relocations are written out in reverse order, so the PAIR comes first.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000291 if (Type == MachO::ARM_RELOC_SECTDIFF ||
292 Type == MachO::ARM_RELOC_LOCAL_SECTDIFF) {
293 MachO::any_relocation_info MRE;
294 MRE.r_word0 = ((0 << 0) |
295 (MachO::ARM_RELOC_PAIR << 24) |
296 (Log2Size << 28) |
297 (IsPCRel << 30) |
298 MachO::R_SCATTERED);
299 MRE.r_word1 = Value2;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000300 Writer->addRelocation(Fragment->getParent(), MRE);
301 }
302
Charles Davis8bdfafd2013-09-01 04:28:48 +0000303 MachO::any_relocation_info MRE;
304 MRE.r_word0 = ((FixupOffset << 0) |
305 (Type << 24) |
306 (Log2Size << 28) |
307 (IsPCRel << 30) |
308 MachO::R_SCATTERED);
309 MRE.r_word1 = Value;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000310 Writer->addRelocation(Fragment->getParent(), MRE);
311}
312
Jim Grosbachdf8ed712012-09-25 18:07:17 +0000313bool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer,
314 const MCAssembler &Asm,
315 const MCFragment &Fragment,
316 unsigned RelocType,
317 const MCSymbolData *SD,
318 uint64_t FixedValue) {
319 // Most cases can be identified purely from the symbol.
320 if (Writer->doesSymbolRequireExternRelocation(SD))
321 return true;
322 int64_t Value = (int64_t)FixedValue; // The displacement is signed.
323 int64_t Range;
324 switch (RelocType) {
325 default:
326 return false;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000327 case MachO::ARM_RELOC_BR24:
Jim Grosbachdf8ed712012-09-25 18:07:17 +0000328 // PC pre-adjustment of 8 for these instructions.
329 Value -= 8;
330 // ARM BL/BLX has a 25-bit offset.
331 Range = 0x1ffffff;
332 break;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000333 case MachO::ARM_THUMB_RELOC_BR22:
Jim Grosbachdf8ed712012-09-25 18:07:17 +0000334 // PC pre-adjustment of 4 for these instructions.
335 Value -= 4;
336 // Thumb BL/BLX has a 24-bit offset.
337 Range = 0xffffff;
338 }
339 // BL/BLX also use external relocations when an internal relocation
340 // would result in the target being out of range. This gives the linker
341 // enough information to generate a branch island.
342 const MCSectionData &SymSD = Asm.getSectionData(
343 SD->getSymbol().getSection());
344 Value += Writer->getSectionAddress(&SymSD);
345 Value -= Writer->getSectionAddress(Fragment.getParent());
346 // If the resultant value would be out of range for an internal relocation,
347 // use an external instead.
348 if (Value > Range || Value < -(Range + 1))
349 return true;
350 return false;
351}
352
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000353void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
354 const MCAssembler &Asm,
355 const MCAsmLayout &Layout,
356 const MCFragment *Fragment,
357 const MCFixup &Fixup,
358 MCValue Target,
359 uint64_t &FixedValue) {
360 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
361 unsigned Log2Size;
Charles Davis8bdfafd2013-09-01 04:28:48 +0000362 unsigned RelocType = MachO::ARM_RELOC_VANILLA;
Jim Grosbach5e5eabb2012-01-26 23:20:15 +0000363 if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size))
364 // If we failed to get fixup kind info, it's because there's no legal
365 // relocation type for the fixup kind. This happens when it's a fixup that's
366 // expected to always be resolvable at assembly time and not have any
367 // relocations needed.
368 Asm.getContext().FatalError(Fixup.getLoc(),
369 "unsupported relocation on symbol");
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000370
371 // If this is a difference or a defined symbol plus an offset, then we need a
372 // scattered relocation entry. Differences always require scattered
373 // relocations.
374 if (Target.getSymB()) {
Charles Davis8bdfafd2013-09-01 04:28:48 +0000375 if (RelocType == MachO::ARM_RELOC_HALF)
Jim Grosbach997614f2012-03-20 17:25:45 +0000376 return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment,
377 Fixup, Target, FixedValue);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000378 return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
Tim Northover1bc367a2014-07-04 10:58:05 +0000379 Target, RelocType, Log2Size,
380 FixedValue);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000381 }
382
383 // Get the symbol data, if any.
Craig Topper062a2ba2014-04-25 05:30:21 +0000384 const MCSymbolData *SD = nullptr;
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000385 if (Target.getSymA())
386 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
387
388 // FIXME: For other platforms, we need to use scattered relocations for
389 // internal relocations with offsets. If this is an internal relocation with
390 // an offset, it also needs a scattered relocation entry.
391 //
392 // Is this right for ARM?
393 uint32_t Offset = Target.getConstant();
Charles Davis8bdfafd2013-09-01 04:28:48 +0000394 if (IsPCRel && RelocType == MachO::ARM_RELOC_VANILLA)
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000395 Offset += 1 << Log2Size;
396 if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
397 return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
Tim Northover1bc367a2014-07-04 10:58:05 +0000398 Target, RelocType, Log2Size,
399 FixedValue);
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000400
401 // See <reloc.h>.
402 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
403 unsigned Index = 0;
404 unsigned IsExtern = 0;
405 unsigned Type = 0;
406
407 if (Target.isAbsolute()) { // constant
408 // FIXME!
409 report_fatal_error("FIXME: relocations to absolute targets "
410 "not yet implemented");
411 } else {
412 // Resolve constant variables.
413 if (SD->getSymbol().isVariable()) {
414 int64_t Res;
415 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
416 Res, Layout, Writer->getSectionAddressMap())) {
417 FixedValue = Res;
418 return;
419 }
420 }
421
422 // Check whether we need an external or internal relocation.
Jim Grosbachdf8ed712012-09-25 18:07:17 +0000423 if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, SD,
424 FixedValue)) {
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000425 IsExtern = 1;
426 Index = SD->getIndex();
427
428 // For external relocations, make sure to offset the fixup value to
429 // compensate for the addend of the symbol address, if it was
430 // undefined. This occurs with weak definitions, for example.
Benjamin Kramer3e67db92014-10-11 15:07:21 +0000431 if (!SD->getSymbol().isUndefined())
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000432 FixedValue -= Layout.getSymbolOffset(SD);
433 } else {
434 // The index is the section ordinal (1-based).
435 const MCSectionData &SymSD = Asm.getSectionData(
436 SD->getSymbol().getSection());
437 Index = SymSD.getOrdinal() + 1;
438 FixedValue += Writer->getSectionAddress(&SymSD);
439 }
440 if (IsPCRel)
441 FixedValue -= Writer->getSectionAddress(Fragment->getParent());
442
443 // The type is determined by the fixup kind.
444 Type = RelocType;
445 }
446
447 // struct relocation_info (8 bytes)
Charles Davis8bdfafd2013-09-01 04:28:48 +0000448 MachO::any_relocation_info MRE;
449 MRE.r_word0 = FixupOffset;
450 MRE.r_word1 = ((Index << 0) |
451 (IsPCRel << 24) |
452 (Log2Size << 25) |
453 (IsExtern << 27) |
454 (Type << 28));
Jim Grosbach997614f2012-03-20 17:25:45 +0000455
456 // Even when it's not a scattered relocation, movw/movt always uses
457 // a PAIR relocation.
Charles Davis8bdfafd2013-09-01 04:28:48 +0000458 if (Type == MachO::ARM_RELOC_HALF) {
Kevin Enderby5c490f12012-07-30 18:46:15 +0000459 // The other-half value only gets populated for the movt and movw
460 // relocation entries.
Dmitri Gribenkoca1e27b2012-09-10 21:26:47 +0000461 uint32_t Value = 0;
Jim Grosbach997614f2012-03-20 17:25:45 +0000462 switch ((unsigned)Fixup.getKind()) {
463 default: break;
Kevin Enderby5c490f12012-07-30 18:46:15 +0000464 case ARM::fixup_arm_movw_lo16:
Kevin Enderby5c490f12012-07-30 18:46:15 +0000465 case ARM::fixup_t2_movw_lo16:
Kevin Enderby5c490f12012-07-30 18:46:15 +0000466 Value = (FixedValue >> 16) & 0xffff;
467 break;
Jim Grosbach997614f2012-03-20 17:25:45 +0000468 case ARM::fixup_arm_movt_hi16:
Jim Grosbach997614f2012-03-20 17:25:45 +0000469 case ARM::fixup_t2_movt_hi16:
Kevin Enderby5c490f12012-07-30 18:46:15 +0000470 Value = FixedValue & 0xffff;
Jim Grosbach997614f2012-03-20 17:25:45 +0000471 break;
472 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000473 MachO::any_relocation_info MREPair;
474 MREPair.r_word0 = Value;
475 MREPair.r_word1 = ((0xffffff << 0) |
476 (Log2Size << 25) |
477 (MachO::ARM_RELOC_PAIR << 28));
Jim Grosbach997614f2012-03-20 17:25:45 +0000478
479 Writer->addRelocation(Fragment->getParent(), MREPair);
480 }
481
Jim Grosbach28fcafb2011-06-24 23:44:37 +0000482 Writer->addRelocation(Fragment->getParent(), MRE);
483}
484
Jim Grosbach2354f872011-06-22 20:14:52 +0000485MCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS,
486 bool Is64Bit,
487 uint32_t CPUType,
488 uint32_t CPUSubtype) {
489 return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit,
490 CPUType,
491 CPUSubtype),
492 OS, /*IsLittleEndian=*/true);
493}