File: | lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp |
Location: | line 561, column 9 |
Description: | Called C++ object pointer is null |
1 | //===-- X86MachObjectWriter.cpp - X86 Mach-O 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/X86MCTargetDesc.h" | |||
11 | #include "MCTargetDesc/X86FixupKinds.h" | |||
12 | #include "llvm/ADT/Twine.h" | |||
13 | #include "llvm/MC/MCAsmInfo.h" | |||
14 | #include "llvm/MC/MCAsmLayout.h" | |||
15 | #include "llvm/MC/MCAssembler.h" | |||
16 | #include "llvm/MC/MCContext.h" | |||
17 | #include "llvm/MC/MCMachObjectWriter.h" | |||
18 | #include "llvm/MC/MCSectionMachO.h" | |||
19 | #include "llvm/MC/MCValue.h" | |||
20 | #include "llvm/Support/ErrorHandling.h" | |||
21 | #include "llvm/Support/Format.h" | |||
22 | #include "llvm/Support/MachO.h" | |||
23 | ||||
24 | using namespace llvm; | |||
25 | ||||
26 | namespace { | |||
27 | class X86MachObjectWriter : public MCMachObjectTargetWriter { | |||
28 | bool recordScatteredRelocation(MachObjectWriter *Writer, | |||
29 | const MCAssembler &Asm, | |||
30 | const MCAsmLayout &Layout, | |||
31 | const MCFragment *Fragment, | |||
32 | const MCFixup &Fixup, | |||
33 | MCValue Target, | |||
34 | unsigned Log2Size, | |||
35 | uint64_t &FixedValue); | |||
36 | void recordTLVPRelocation(MachObjectWriter *Writer, | |||
37 | const MCAssembler &Asm, | |||
38 | const MCAsmLayout &Layout, | |||
39 | const MCFragment *Fragment, | |||
40 | const MCFixup &Fixup, | |||
41 | MCValue Target, | |||
42 | uint64_t &FixedValue); | |||
43 | ||||
44 | void RecordX86Relocation(MachObjectWriter *Writer, | |||
45 | const MCAssembler &Asm, | |||
46 | const MCAsmLayout &Layout, | |||
47 | const MCFragment *Fragment, | |||
48 | const MCFixup &Fixup, | |||
49 | MCValue Target, | |||
50 | uint64_t &FixedValue); | |||
51 | void RecordX86_64Relocation(MachObjectWriter *Writer, MCAssembler &Asm, | |||
52 | const MCAsmLayout &Layout, | |||
53 | const MCFragment *Fragment, const MCFixup &Fixup, | |||
54 | MCValue Target, uint64_t &FixedValue); | |||
55 | ||||
56 | public: | |||
57 | X86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) | |||
58 | : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} | |||
59 | ||||
60 | void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, | |||
61 | const MCAsmLayout &Layout, const MCFragment *Fragment, | |||
62 | const MCFixup &Fixup, MCValue Target, | |||
63 | uint64_t &FixedValue) override { | |||
64 | if (Writer->is64Bit()) | |||
65 | RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, | |||
66 | FixedValue); | |||
67 | else | |||
68 | RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, | |||
69 | FixedValue); | |||
70 | } | |||
71 | }; | |||
72 | } | |||
73 | ||||
74 | static bool isFixupKindRIPRel(unsigned Kind) { | |||
75 | return Kind == X86::reloc_riprel_4byte || | |||
76 | Kind == X86::reloc_riprel_4byte_movq_load; | |||
77 | } | |||
78 | ||||
79 | static unsigned getFixupKindLog2Size(unsigned Kind) { | |||
80 | switch (Kind) { | |||
81 | default: | |||
82 | llvm_unreachable("invalid fixup kind!")::llvm::llvm_unreachable_internal("invalid fixup kind!", "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp" , 82); | |||
83 | case FK_PCRel_1: | |||
84 | case FK_Data_1: return 0; | |||
85 | case FK_PCRel_2: | |||
86 | case FK_Data_2: return 1; | |||
87 | case FK_PCRel_4: | |||
88 | // FIXME: Remove these!!! | |||
89 | case X86::reloc_riprel_4byte: | |||
90 | case X86::reloc_riprel_4byte_movq_load: | |||
91 | case X86::reloc_signed_4byte: | |||
92 | case FK_Data_4: return 2; | |||
93 | case FK_Data_8: return 3; | |||
94 | } | |||
95 | } | |||
96 | ||||
97 | void X86MachObjectWriter::RecordX86_64Relocation( | |||
98 | MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, | |||
99 | const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, | |||
100 | uint64_t &FixedValue) { | |||
101 | unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); | |||
102 | unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); | |||
103 | unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); | |||
104 | ||||
105 | // See <reloc.h>. | |||
106 | uint32_t FixupOffset = | |||
107 | Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); | |||
108 | uint32_t FixupAddress = | |||
109 | Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); | |||
110 | int64_t Value = 0; | |||
111 | unsigned Index = 0; | |||
112 | unsigned IsExtern = 0; | |||
113 | unsigned Type = 0; | |||
114 | const MCSymbol *RelSymbol = nullptr; | |||
115 | ||||
116 | Value = Target.getConstant(); | |||
117 | ||||
118 | if (IsPCRel) { | |||
119 | // Compensate for the relocation offset, Darwin x86_64 relocations only have | |||
120 | // the addend and appear to have attempted to define it to be the actual | |||
121 | // expression addend without the PCrel bias. However, instructions with data | |||
122 | // following the relocation are not accommodated for (see comment below | |||
123 | // regarding SIGNED{1,2,4}), so it isn't exactly that either. | |||
124 | Value += 1LL << Log2Size; | |||
125 | } | |||
126 | ||||
127 | if (Target.isAbsolute()) { // constant | |||
128 | // SymbolNum of 0 indicates the absolute section. | |||
129 | Type = MachO::X86_64_RELOC_UNSIGNED; | |||
130 | ||||
131 | // FIXME: I believe this is broken, I don't think the linker can understand | |||
132 | // it. I think it would require a local relocation, but I'm not sure if that | |||
133 | // would work either. The official way to get an absolute PCrel relocation | |||
134 | // is to use an absolute symbol (which we don't support yet). | |||
135 | if (IsPCRel) { | |||
136 | IsExtern = 1; | |||
137 | Type = MachO::X86_64_RELOC_BRANCH; | |||
138 | } | |||
139 | } else if (Target.getSymB()) { // A - B + constant | |||
140 | const MCSymbol *A = &Target.getSymA()->getSymbol(); | |||
141 | if (A->isTemporary()) | |||
142 | A = &Writer->findAliasedSymbol(*A); | |||
143 | const MCSymbol *A_Base = Asm.getAtom(*A); | |||
144 | ||||
145 | const MCSymbol *B = &Target.getSymB()->getSymbol(); | |||
146 | if (B->isTemporary()) | |||
147 | B = &Writer->findAliasedSymbol(*B); | |||
148 | const MCSymbol *B_Base = Asm.getAtom(*B); | |||
149 | ||||
150 | // Neither symbol can be modified. | |||
151 | if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None || | |||
152 | Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) { | |||
153 | Asm.getContext().reportError(Fixup.getLoc(), | |||
154 | "unsupported relocation of modified symbol"); | |||
155 | return; | |||
156 | } | |||
157 | ||||
158 | // We don't support PCrel relocations of differences. Darwin 'as' doesn't | |||
159 | // implement most of these correctly. | |||
160 | if (IsPCRel) { | |||
161 | Asm.getContext().reportError( | |||
162 | Fixup.getLoc(), "unsupported pc-relative relocation of difference"); | |||
163 | return; | |||
164 | } | |||
165 | ||||
166 | // The support for the situation where one or both of the symbols would | |||
167 | // require a local relocation is handled just like if the symbols were | |||
168 | // external. This is certainly used in the case of debug sections where the | |||
169 | // section has only temporary symbols and thus the symbols don't have base | |||
170 | // symbols. This is encoded using the section ordinal and non-extern | |||
171 | // relocation entries. | |||
172 | ||||
173 | // Darwin 'as' doesn't emit correct relocations for this (it ends up with a | |||
174 | // single SIGNED relocation); reject it for now. Except the case where both | |||
175 | // symbols don't have a base, equal but both NULL. | |||
176 | if (A_Base == B_Base && A_Base) { | |||
177 | Asm.getContext().reportError( | |||
178 | Fixup.getLoc(), "unsupported relocation with identical base"); | |||
179 | return; | |||
180 | } | |||
181 | ||||
182 | // A subtraction expression where either symbol is undefined is a | |||
183 | // non-relocatable expression. | |||
184 | if (A->isUndefined() || B->isUndefined()) { | |||
185 | StringRef Name = A->isUndefined() ? A->getName() : B->getName(); | |||
186 | Asm.getContext().reportError(Fixup.getLoc(), | |||
187 | "unsupported relocation with subtraction expression, symbol '" + | |||
188 | Name + "' can not be undefined in a subtraction expression"); | |||
189 | return; | |||
190 | } | |||
191 | ||||
192 | Value += Writer->getSymbolAddress(*A, Layout) - | |||
193 | (!A_Base ? 0 : Writer->getSymbolAddress(*A_Base, Layout)); | |||
194 | Value -= Writer->getSymbolAddress(*B, Layout) - | |||
195 | (!B_Base ? 0 : Writer->getSymbolAddress(*B_Base, Layout)); | |||
196 | ||||
197 | if (!A_Base) | |||
198 | Index = A->getFragment()->getParent()->getOrdinal() + 1; | |||
199 | Type = MachO::X86_64_RELOC_UNSIGNED; | |||
200 | ||||
201 | MachO::any_relocation_info MRE; | |||
202 | MRE.r_word0 = FixupOffset; | |||
203 | MRE.r_word1 = | |||
204 | (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28); | |||
205 | Writer->addRelocation(A_Base, Fragment->getParent(), MRE); | |||
206 | ||||
207 | if (B_Base) | |||
208 | RelSymbol = B_Base; | |||
209 | else | |||
210 | Index = B->getFragment()->getParent()->getOrdinal() + 1; | |||
211 | Type = MachO::X86_64_RELOC_SUBTRACTOR; | |||
212 | } else { | |||
213 | const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); | |||
214 | if (Symbol->isTemporary() && Value) { | |||
215 | const MCSection &Sec = Symbol->getSection(); | |||
216 | if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec)) | |||
217 | Symbol->setUsedInReloc(); | |||
218 | } | |||
219 | RelSymbol = Asm.getAtom(*Symbol); | |||
220 | ||||
221 | // Relocations inside debug sections always use local relocations when | |||
222 | // possible. This seems to be done because the debugger doesn't fully | |||
223 | // understand x86_64 relocation entries, and expects to find values that | |||
224 | // have already been fixed up. | |||
225 | if (Symbol->isInSection()) { | |||
226 | const MCSectionMachO &Section = | |||
227 | static_cast<const MCSectionMachO &>(*Fragment->getParent()); | |||
228 | if (Section.hasAttribute(MachO::S_ATTR_DEBUG)) | |||
229 | RelSymbol = nullptr; | |||
230 | } | |||
231 | ||||
232 | // x86_64 almost always uses external relocations, except when there is no | |||
233 | // symbol to use as a base address (a local symbol with no preceding | |||
234 | // non-local symbol). | |||
235 | if (RelSymbol) { | |||
236 | // Add the local offset, if needed. | |||
237 | if (RelSymbol != Symbol) | |||
238 | Value += Layout.getSymbolOffset(*Symbol) - | |||
239 | Layout.getSymbolOffset(*RelSymbol); | |||
240 | } else if (Symbol->isInSection() && !Symbol->isVariable()) { | |||
241 | // The index is the section ordinal (1-based). | |||
242 | Index = Symbol->getFragment()->getParent()->getOrdinal() + 1; | |||
243 | Value += Writer->getSymbolAddress(*Symbol, Layout); | |||
244 | ||||
245 | if (IsPCRel) | |||
246 | Value -= FixupAddress + (1 << Log2Size); | |||
247 | } else if (Symbol->isVariable()) { | |||
248 | const MCExpr *Value = Symbol->getVariableValue(); | |||
249 | int64_t Res; | |||
250 | bool isAbs = Value->evaluateAsAbsolute(Res, Layout, | |||
251 | Writer->getSectionAddressMap()); | |||
252 | if (isAbs) { | |||
253 | FixedValue = Res; | |||
254 | return; | |||
255 | } else { | |||
256 | Asm.getContext().reportError(Fixup.getLoc(), | |||
257 | "unsupported relocation of variable '" + | |||
258 | Symbol->getName() + "'"); | |||
259 | return; | |||
260 | } | |||
261 | } else { | |||
262 | Asm.getContext().reportError( | |||
263 | Fixup.getLoc(), "unsupported relocation of undefined symbol '" + | |||
264 | Symbol->getName() + "'"); | |||
265 | return; | |||
266 | } | |||
267 | ||||
268 | MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); | |||
269 | if (IsPCRel) { | |||
270 | if (IsRIPRel) { | |||
271 | if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { | |||
272 | // x86_64 distinguishes movq foo@GOTPCREL so that the linker can | |||
273 | // rewrite the movq to an leaq at link time if the symbol ends up in | |||
274 | // the same linkage unit. | |||
275 | if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) | |||
276 | Type = MachO::X86_64_RELOC_GOT_LOAD; | |||
277 | else | |||
278 | Type = MachO::X86_64_RELOC_GOT; | |||
279 | } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { | |||
280 | Type = MachO::X86_64_RELOC_TLV; | |||
281 | } else if (Modifier != MCSymbolRefExpr::VK_None) { | |||
282 | Asm.getContext().reportError( | |||
283 | Fixup.getLoc(), "unsupported symbol modifier in relocation"); | |||
284 | return; | |||
285 | } else { | |||
286 | Type = MachO::X86_64_RELOC_SIGNED; | |||
287 | ||||
288 | // The Darwin x86_64 relocation format has a problem where it cannot | |||
289 | // encode an address (L<foo> + <constant>) which is outside the atom | |||
290 | // containing L<foo>. Generally, this shouldn't occur but it does | |||
291 | // happen when we have a RIPrel instruction with data following the | |||
292 | // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel | |||
293 | // adjustment Darwin x86_64 uses, the offset is still negative and the | |||
294 | // linker has no way to recognize this. | |||
295 | // | |||
296 | // To work around this, Darwin uses several special relocation types | |||
297 | // to indicate the offsets. However, the specification or | |||
298 | // implementation of these seems to also be incomplete; they should | |||
299 | // adjust the addend as well based on the actual encoded instruction | |||
300 | // (the additional bias), but instead appear to just look at the final | |||
301 | // offset. | |||
302 | switch (-(Target.getConstant() + (1LL << Log2Size))) { | |||
303 | case 1: Type = MachO::X86_64_RELOC_SIGNED_1; break; | |||
304 | case 2: Type = MachO::X86_64_RELOC_SIGNED_2; break; | |||
305 | case 4: Type = MachO::X86_64_RELOC_SIGNED_4; break; | |||
306 | } | |||
307 | } | |||
308 | } else { | |||
309 | if (Modifier != MCSymbolRefExpr::VK_None) { | |||
310 | Asm.getContext().reportError( | |||
311 | Fixup.getLoc(), | |||
312 | "unsupported symbol modifier in branch relocation"); | |||
313 | return; | |||
314 | } | |||
315 | ||||
316 | Type = MachO::X86_64_RELOC_BRANCH; | |||
317 | } | |||
318 | } else { | |||
319 | if (Modifier == MCSymbolRefExpr::VK_GOT) { | |||
320 | Type = MachO::X86_64_RELOC_GOT; | |||
321 | } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { | |||
322 | // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which | |||
323 | // case all we do is set the PCrel bit in the relocation entry; this is | |||
324 | // used with exception handling, for example. The source is required to | |||
325 | // include any necessary offset directly. | |||
326 | Type = MachO::X86_64_RELOC_GOT; | |||
327 | IsPCRel = 1; | |||
328 | } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { | |||
329 | Asm.getContext().reportError( | |||
330 | Fixup.getLoc(), "TLVP symbol modifier should have been rip-rel"); | |||
331 | return; | |||
332 | } else if (Modifier != MCSymbolRefExpr::VK_None) { | |||
333 | Asm.getContext().reportError( | |||
334 | Fixup.getLoc(), "unsupported symbol modifier in relocation"); | |||
335 | return; | |||
336 | } else { | |||
337 | Type = MachO::X86_64_RELOC_UNSIGNED; | |||
338 | unsigned Kind = Fixup.getKind(); | |||
339 | if (Kind == X86::reloc_signed_4byte) { | |||
340 | Asm.getContext().reportError( | |||
341 | Fixup.getLoc(), | |||
342 | "32-bit absolute addressing is not supported in 64-bit mode"); | |||
343 | return; | |||
344 | } | |||
345 | } | |||
346 | } | |||
347 | } | |||
348 | ||||
349 | // x86_64 always writes custom values into the fixups. | |||
350 | FixedValue = Value; | |||
351 | ||||
352 | // struct relocation_info (8 bytes) | |||
353 | MachO::any_relocation_info MRE; | |||
354 | MRE.r_word0 = FixupOffset; | |||
355 | MRE.r_word1 = (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | | |||
356 | (IsExtern << 27) | (Type << 28); | |||
357 | Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE); | |||
358 | } | |||
359 | ||||
360 | bool X86MachObjectWriter::recordScatteredRelocation(MachObjectWriter *Writer, | |||
361 | const MCAssembler &Asm, | |||
362 | const MCAsmLayout &Layout, | |||
363 | const MCFragment *Fragment, | |||
364 | const MCFixup &Fixup, | |||
365 | MCValue Target, | |||
366 | unsigned Log2Size, | |||
367 | uint64_t &FixedValue) { | |||
368 | uint64_t OriginalFixedValue = FixedValue; | |||
369 | uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); | |||
370 | unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); | |||
371 | unsigned Type = MachO::GENERIC_RELOC_VANILLA; | |||
372 | ||||
373 | // See <reloc.h>. | |||
374 | const MCSymbol *A = &Target.getSymA()->getSymbol(); | |||
375 | ||||
376 | if (!A->getFragment()) { | |||
377 | Asm.getContext().reportError( | |||
378 | Fixup.getLoc(), | |||
379 | "symbol '" + A->getName() + | |||
380 | "' can not be undefined in a subtraction expression"); | |||
381 | return false; | |||
382 | } | |||
383 | ||||
384 | uint32_t Value = Writer->getSymbolAddress(*A, Layout); | |||
385 | uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent()); | |||
386 | FixedValue += SecAddr; | |||
387 | uint32_t Value2 = 0; | |||
388 | ||||
389 | if (const MCSymbolRefExpr *B = Target.getSymB()) { | |||
390 | const MCSymbol *SB = &B->getSymbol(); | |||
391 | ||||
392 | if (!SB->getFragment()) { | |||
393 | Asm.getContext().reportError( | |||
394 | Fixup.getLoc(), | |||
395 | "symbol '" + B->getSymbol().getName() + | |||
396 | "' can not be undefined in a subtraction expression"); | |||
397 | return false; | |||
398 | } | |||
399 | ||||
400 | // Select the appropriate difference relocation type. | |||
401 | // | |||
402 | // Note that there is no longer any semantic difference between these two | |||
403 | // relocation types from the linkers point of view, this is done solely for | |||
404 | // pedantic compatibility with 'as'. | |||
405 | Type = A->isExternal() ? (unsigned)MachO::GENERIC_RELOC_SECTDIFF | |||
406 | : (unsigned)MachO::GENERIC_RELOC_LOCAL_SECTDIFF; | |||
407 | Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout); | |||
408 | FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent()); | |||
409 | } | |||
410 | ||||
411 | // Relocations are written out in reverse order, so the PAIR comes first. | |||
412 | if (Type == MachO::GENERIC_RELOC_SECTDIFF || | |||
413 | Type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { | |||
414 | // If the offset is too large to fit in a scattered relocation, | |||
415 | // we're hosed. It's an unfortunate limitation of the MachO format. | |||
416 | if (FixupOffset > 0xffffff) { | |||
417 | char Buffer[32]; | |||
418 | format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer)); | |||
419 | Asm.getContext().reportError(Fixup.getLoc(), | |||
420 | Twine("Section too large, can't encode " | |||
421 | "r_address (") + Buffer + | |||
422 | ") into 24 bits of scattered " | |||
423 | "relocation entry."); | |||
424 | return false; | |||
425 | } | |||
426 | ||||
427 | MachO::any_relocation_info MRE; | |||
428 | MRE.r_word0 = ((0 << 0) | // r_address | |||
429 | (MachO::GENERIC_RELOC_PAIR << 24) | // r_type | |||
430 | (Log2Size << 28) | | |||
431 | (IsPCRel << 30) | | |||
432 | MachO::R_SCATTERED); | |||
433 | MRE.r_word1 = Value2; | |||
434 | Writer->addRelocation(nullptr, Fragment->getParent(), MRE); | |||
435 | } else { | |||
436 | // If the offset is more than 24-bits, it won't fit in a scattered | |||
437 | // relocation offset field, so we fall back to using a non-scattered | |||
438 | // relocation. This is a bit risky, as if the offset reaches out of | |||
439 | // the block and the linker is doing scattered loading on this | |||
440 | // symbol, things can go badly. | |||
441 | // | |||
442 | // Required for 'as' compatibility. | |||
443 | if (FixupOffset > 0xffffff) { | |||
444 | FixedValue = OriginalFixedValue; | |||
445 | return false; | |||
446 | } | |||
447 | } | |||
448 | ||||
449 | MachO::any_relocation_info MRE; | |||
450 | MRE.r_word0 = ((FixupOffset << 0) | | |||
451 | (Type << 24) | | |||
452 | (Log2Size << 28) | | |||
453 | (IsPCRel << 30) | | |||
454 | MachO::R_SCATTERED); | |||
455 | MRE.r_word1 = Value; | |||
456 | Writer->addRelocation(nullptr, Fragment->getParent(), MRE); | |||
457 | return true; | |||
458 | } | |||
459 | ||||
460 | void X86MachObjectWriter::recordTLVPRelocation(MachObjectWriter *Writer, | |||
461 | const MCAssembler &Asm, | |||
462 | const MCAsmLayout &Layout, | |||
463 | const MCFragment *Fragment, | |||
464 | const MCFixup &Fixup, | |||
465 | MCValue Target, | |||
466 | uint64_t &FixedValue) { | |||
467 | assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&((Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && !is64Bit() && "Should only be called with a 32-bit TLVP relocation!" ) ? static_cast<void> (0) : __assert_fail ("Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && !is64Bit() && \"Should only be called with a 32-bit TLVP relocation!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp" , 469, __PRETTY_FUNCTION__)) | |||
468 | !is64Bit() &&((Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && !is64Bit() && "Should only be called with a 32-bit TLVP relocation!" ) ? static_cast<void> (0) : __assert_fail ("Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && !is64Bit() && \"Should only be called with a 32-bit TLVP relocation!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp" , 469, __PRETTY_FUNCTION__)) | |||
469 | "Should only be called with a 32-bit TLVP relocation!")((Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && !is64Bit() && "Should only be called with a 32-bit TLVP relocation!" ) ? static_cast<void> (0) : __assert_fail ("Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && !is64Bit() && \"Should only be called with a 32-bit TLVP relocation!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.8~svn257205/lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp" , 469, __PRETTY_FUNCTION__)); | |||
470 | ||||
471 | unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); | |||
472 | uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); | |||
473 | unsigned IsPCRel = 0; | |||
474 | ||||
475 | // We're only going to have a second symbol in pic mode and it'll be a | |||
476 | // subtraction from the picbase. For 32-bit pic the addend is the difference | |||
477 | // between the picbase and the next address. For 32-bit static the addend is | |||
478 | // zero. | |||
479 | if (Target.getSymB()) { | |||
480 | // If this is a subtraction then we're pcrel. | |||
481 | uint32_t FixupAddress = | |||
482 | Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); | |||
483 | IsPCRel = 1; | |||
484 | FixedValue = | |||
485 | FixupAddress - | |||
486 | Writer->getSymbolAddress(Target.getSymB()->getSymbol(), Layout) + | |||
487 | Target.getConstant(); | |||
488 | FixedValue += 1ULL << Log2Size; | |||
489 | } else { | |||
490 | FixedValue = 0; | |||
491 | } | |||
492 | ||||
493 | // struct relocation_info (8 bytes) | |||
494 | MachO::any_relocation_info MRE; | |||
495 | MRE.r_word0 = Value; | |||
496 | MRE.r_word1 = | |||
497 | (IsPCRel << 24) | (Log2Size << 25) | (MachO::GENERIC_RELOC_TLV << 28); | |||
498 | Writer->addRelocation(&Target.getSymA()->getSymbol(), Fragment->getParent(), | |||
499 | MRE); | |||
500 | } | |||
501 | ||||
502 | void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer, | |||
503 | const MCAssembler &Asm, | |||
504 | const MCAsmLayout &Layout, | |||
505 | const MCFragment *Fragment, | |||
506 | const MCFixup &Fixup, | |||
507 | MCValue Target, | |||
508 | uint64_t &FixedValue) { | |||
509 | unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); | |||
510 | unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); | |||
511 | ||||
512 | // If this is a 32-bit TLVP reloc it's handled a bit differently. | |||
513 | if (Target.getSymA() && | |||
514 | Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) { | |||
515 | recordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, | |||
516 | FixedValue); | |||
517 | return; | |||
518 | } | |||
519 | ||||
520 | // If this is a difference or a defined symbol plus an offset, then we need a | |||
521 | // scattered relocation entry. Differences always require scattered | |||
522 | // relocations. | |||
523 | if (Target.getSymB()) { | |||
| ||||
524 | recordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, | |||
525 | Target, Log2Size, FixedValue); | |||
526 | return; | |||
527 | } | |||
528 | ||||
529 | // Get the symbol data, if any. | |||
530 | const MCSymbol *A = nullptr; | |||
531 | if (Target.getSymA()) | |||
532 | A = &Target.getSymA()->getSymbol(); | |||
533 | ||||
534 | // If this is an internal relocation with an offset, it also needs a scattered | |||
535 | // relocation entry. | |||
536 | uint32_t Offset = Target.getConstant(); | |||
537 | if (IsPCRel) | |||
538 | Offset += 1 << Log2Size; | |||
539 | // Try to record the scattered relocation if needed. Fall back to non | |||
540 | // scattered if necessary (see comments in recordScatteredRelocation() | |||
541 | // for details). | |||
542 | if (Offset && A && !Writer->doesSymbolRequireExternRelocation(*A) && | |||
543 | recordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, | |||
544 | Log2Size, FixedValue)) | |||
545 | return; | |||
546 | ||||
547 | // See <reloc.h>. | |||
548 | uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); | |||
549 | unsigned Index = 0; | |||
550 | unsigned Type = 0; | |||
551 | const MCSymbol *RelSymbol = nullptr; | |||
552 | ||||
553 | if (Target.isAbsolute()) { // constant | |||
554 | // SymbolNum of 0 indicates the absolute section. | |||
555 | // | |||
556 | // FIXME: Currently, these are never generated (see code below). I cannot | |||
557 | // find a case where they are actually emitted. | |||
558 | Type = MachO::GENERIC_RELOC_VANILLA; | |||
559 | } else { | |||
560 | // Resolve constant variables. | |||
561 | if (A->isVariable()) { | |||
| ||||
562 | int64_t Res; | |||
563 | if (A->getVariableValue()->evaluateAsAbsolute( | |||
564 | Res, Layout, Writer->getSectionAddressMap())) { | |||
565 | FixedValue = Res; | |||
566 | return; | |||
567 | } | |||
568 | } | |||
569 | ||||
570 | // Check whether we need an external or internal relocation. | |||
571 | if (Writer->doesSymbolRequireExternRelocation(*A)) { | |||
572 | RelSymbol = A; | |||
573 | // For external relocations, make sure to offset the fixup value to | |||
574 | // compensate for the addend of the symbol address, if it was | |||
575 | // undefined. This occurs with weak definitions, for example. | |||
576 | if (!A->isUndefined()) | |||
577 | FixedValue -= Layout.getSymbolOffset(*A); | |||
578 | } else { | |||
579 | // The index is the section ordinal (1-based). | |||
580 | const MCSection &Sec = A->getSection(); | |||
581 | Index = Sec.getOrdinal() + 1; | |||
582 | FixedValue += Writer->getSectionAddress(&Sec); | |||
583 | } | |||
584 | if (IsPCRel) | |||
585 | FixedValue -= Writer->getSectionAddress(Fragment->getParent()); | |||
586 | ||||
587 | Type = MachO::GENERIC_RELOC_VANILLA; | |||
588 | } | |||
589 | ||||
590 | // struct relocation_info (8 bytes) | |||
591 | MachO::any_relocation_info MRE; | |||
592 | MRE.r_word0 = FixupOffset; | |||
593 | MRE.r_word1 = | |||
594 | (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28); | |||
595 | Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE); | |||
596 | } | |||
597 | ||||
598 | MCObjectWriter *llvm::createX86MachObjectWriter(raw_pwrite_stream &OS, | |||
599 | bool Is64Bit, uint32_t CPUType, | |||
600 | uint32_t CPUSubtype) { | |||
601 | return createMachObjectWriter(new X86MachObjectWriter(Is64Bit, | |||
602 | CPUType, | |||
603 | CPUSubtype), | |||
604 | OS, /*IsLittleEndian=*/true); | |||
605 | } |