LLVM: lib/Target/X86/MCTargetDesc/X86MachObjectWriter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
24
25using namespace llvm;
26
27namespace {
29 bool recordScatteredRelocation(MachObjectWriter *Writer,
30 const MCAssembler &Asm,
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 MCFragment *Fragment,
39 const MCFixup &Fixup,
40 MCValue Target,
41 uint64_t &FixedValue);
42
43 void RecordX86Relocation(MachObjectWriter *Writer,
44 const MCAssembler &Asm,
45 const MCFragment *Fragment,
46 const MCFixup &Fixup,
47 MCValue Target,
48 uint64_t &FixedValue);
49 void RecordX86_64Relocation(MachObjectWriter *Writer, MCAssembler &Asm,
50 const MCFragment *Fragment, const MCFixup &Fixup,
51 MCValue Target, uint64_t &FixedValue);
52
53public:
54 X86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
55 : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
56
57 void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
58 const MCFragment *Fragment, const MCFixup &Fixup,
59 MCValue Target, uint64_t &FixedValue) override {
61 RecordX86_64Relocation(Writer, Asm, Fragment, Fixup, Target, FixedValue);
62 else
63 RecordX86Relocation(Writer, Asm, Fragment, Fixup, Target, FixedValue);
64 }
65};
66}
67
77
79 switch (Kind) {
80 default:
84
97 }
98}
99
100void X86MachObjectWriter::RecordX86_64Relocation(
103 unsigned IsPCRel = Fixup.isPCRel();
106
107
108 uint32_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
109 uint32_t FixupAddress =
111 int64_t Value = 0;
112 unsigned Index = 0;
113 unsigned IsExtern = 0;
114 unsigned Type = 0;
115 const MCSymbol *RelSymbol = nullptr;
116
118
119 if (IsPCRel) {
120
121
122
123
124
125 Value += 1LL << Log2Size;
126 }
127
128 if (Target.isAbsolute()) {
129
131
132
133
134
135
136 if (IsPCRel) {
137 IsExtern = 1;
139 }
140 } else if (Target.getSubSym()) {
142 if (A->isTemporary())
145
147 if (B->isTemporary())
150
151
152 if (Target.getSpecifier()) {
153 reportError(Fixup.getLoc(), "unsupported relocation of modified symbol");
154 return;
155 }
156
157
158
159 if (IsPCRel) {
161 "unsupported pc-relative relocation of difference");
162 return;
163 }
164
165
166
167
168
169
170
171
172
173
174
175 if (A_Base == B_Base && A_Base) {
176 reportError(Fixup.getLoc(), "unsupported relocation with identical base");
177 return;
178 }
179
180
181
182 if (A->isUndefined() || B->isUndefined()) {
183 StringRef Name = A->isUndefined() ? A->getName() : B->getName();
186 "unsupported relocation with subtraction expression, symbol '" +
187 Name + "' can not be undefined in a subtraction expression");
188 return;
189 }
190
195
196 if (!A_Base)
197 Index = A->getFragment()->getParent()->getOrdinal() + 1;
199
200 MachO::any_relocation_info MRE;
201 MRE.r_word0 = FixupOffset;
203 (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
205
206 if (B_Base)
207 RelSymbol = B_Base;
208 else
209 Index = B->getFragment()->getParent()->getOrdinal() + 1;
211 } else {
214 const MCSection &Sec = Symbol->getSection();
216 Symbol->setUsedInReloc();
217 }
218 RelSymbol = Writer->getAtom(*Symbol);
219
220
221
222
223
224 if (Symbol->isInSection()) {
225 const MCSectionMachO &Section =
226 static_cast<const MCSectionMachO &>(*Fragment->getParent());
228 RelSymbol = nullptr;
229 }
230
231
232
233
234 if (RelSymbol) {
235
236 if (RelSymbol != Symbol)
237 Value += Asm.getSymbolOffset(*Symbol) - Asm.getSymbolOffset(*RelSymbol);
238 } else if (Symbol->isInSection() && ->isVariable()) {
239
240 Index = Symbol->getFragment()->getParent()->getOrdinal() + 1;
242
243 if (IsPCRel)
244 Value -= FixupAddress + (1 << Log2Size);
245 } else if (Symbol->isVariable()) {
247 return;
248 } else {
250 "unsupported relocation of undefined symbol '" +
251 Symbol->getName() + "'");
252 return;
253 }
254
256 if (IsPCRel) {
257 if (IsRIPRel) {
259
260
261
264 else
268 } else if (Specifier) {
270 "unsupported symbol modifier in relocation");
271 return;
272 } else {
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 switch (-(Target.getConstant() + (1LL << Log2Size))) {
293 }
294 }
295 } else {
296 if (Specifier) {
298 "unsupported symbol modifier in branch relocation");
299 return;
300 }
301
303 }
304 } else {
308
309
310
311
313 IsPCRel = 1;
316 "TLVP symbol modifier should have been rip-rel");
317 return;
318 } else if (Specifier) {
320 "unsupported symbol modifier in relocation");
321 return;
322 } else {
327 "32-bit absolute addressing is not supported in 64-bit mode");
328 return;
329 }
330 }
331 }
332 }
333
334
335 FixedValue = Value;
336
337
338 MachO::any_relocation_info MRE;
339 MRE.r_word0 = FixupOffset;
340 MRE.r_word1 = (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
341 (IsExtern << 27) | (Type << 28);
343}
344
345bool X86MachObjectWriter::recordScatteredRelocation(MachObjectWriter *Writer,
346 const MCAssembler &Asm,
347 const MCFragment *Fragment,
348 const MCFixup &Fixup,
349 MCValue Target,
350 unsigned Log2Size,
351 uint64_t &FixedValue) {
352 uint64_t OriginalFixedValue = FixedValue;
353 uint32_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
354 unsigned IsPCRel = Fixup.isPCRel();
356
357
358 auto *A = static_cast<const MCSymbolMachO *>(Target.getAddSym());
359 if (->getFragment()) {
361 "symbol '" + A->getName() +
362 "' can not be undefined in a subtraction expression");
363 return false;
364 }
365
367 uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
368 FixedValue += SecAddr;
369 uint32_t Value2 = 0;
370
371 if (const MCSymbol *SB = Target.getSubSym()) {
372 if (!SB->getFragment()) {
374 "symbol '" + SB->getName() +
375 "' can not be undefined in a subtraction expression");
376 return false;
377 }
378
379
380
381
382
383
387 FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
388 }
389
390
393
394
395 if (FixupOffset > 0xffffff) {
396 char Buffer[32];
397 format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
398 reportError(Fixup.getLoc(), Twine("Section too large, can't encode "
399 "r_address (") +
400 Buffer +
401 ") into 24 bits of scattered "
402 "relocation entry.");
403 return false;
404 }
405
406 MachO::any_relocation_info MRE;
407 MRE.r_word0 = ((0 << 0) |
409 (Log2Size << 28) |
410 (IsPCRel << 30) |
414 } else {
415
416
417
418
419
420
421
422 if (FixupOffset > 0xffffff) {
423 FixedValue = OriginalFixedValue;
424 return false;
425 }
426 }
427
428 MachO::any_relocation_info MRE;
429 MRE.r_word0 = ((FixupOffset << 0) |
430 (Type << 24) |
431 (Log2Size << 28) |
432 (IsPCRel << 30) |
436 return true;
437}
438
439void X86MachObjectWriter::recordTLVPRelocation(MachObjectWriter *Writer,
440 const MCAssembler &Asm,
441 const MCFragment *Fragment,
442 const MCFixup &Fixup,
443 MCValue Target,
444 uint64_t &FixedValue) {
447 "Should only be called with a 32-bit TLVP relocation!");
448
450 uint32_t Value = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
451 unsigned IsPCRel = 0;
452
453
454
455
456
457 if (auto *SymB = Target.getSubSym()) {
458
459 uint32_t FixupAddress =
461 IsPCRel = 1;
462 FixedValue =
464 FixedValue += 1ULL << Log2Size;
465 } else {
466 FixedValue = 0;
467 }
468
469
470 MachO::any_relocation_info MRE;
475}
476
477void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
478 const MCAssembler &Asm,
479 const MCFragment *Fragment,
480 const MCFixup &Fixup,
481 MCValue Target,
482 uint64_t &FixedValue) {
483 unsigned IsPCRel = Fixup.isPCRel();
486
487
489 recordTLVPRelocation(Writer, Asm, Fragment, Fixup, Target, FixedValue);
490 return;
491 }
492
493
494
495
496 if (Target.getSubSym()) {
497 recordScatteredRelocation(Writer, Asm, Fragment, Fixup, Target, Log2Size,
498 FixedValue);
499 return;
500 }
501
502
503
505 if (IsPCRel)
506 Offset += 1 << Log2Size;
507
508
509
510
512 recordScatteredRelocation(Writer, Asm, Fragment, Fixup, Target, Log2Size,
513 FixedValue))
514 return;
515
516
517 uint32_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
518 unsigned Index = 0;
519 unsigned Type = 0;
520 const MCSymbol *RelSymbol = nullptr;
521
522 if (Target.isAbsolute()) {
523
524
525
526
528 } else {
529 assert(A && "Unknown symbol data");
530
531
532 if (A->isVariable()) {
533 MCValue Val;
534 bool Relocatable =
535 A->getVariableValue()->evaluateAsRelocatable(Val, &Asm);
541 isAbs = true;
542 }
543 if (isAbs) {
544 FixedValue = Res;
545 return;
546 }
547 }
548
549
551 RelSymbol = A;
552
553
554
555 if (->isUndefined())
556 FixedValue -= Asm.getSymbolOffset(*A);
557 } else {
558
559 const MCSection &Sec = A->getSection();
562 }
563 if (IsPCRel)
565
567 }
568
569
570 MachO::any_relocation_info MRE;
571 MRE.r_word0 = FixupOffset;
573 (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
575}
576
577std::unique_ptr
580 return std::make_unique(Is64Bit, CPUType, CPUSubtype);
581}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Error reportError(StringRef Message)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
PowerPC TLS Dynamic Call Fixup
static bool is64Bit(const char *name)
static bool isFixupKindRIPRel(unsigned Kind)
Definition X86MachObjectWriter.cpp:68
static bool isSectionAtomizableBySymbols(const MCSection &Section)
True if the section is atomized using the symbols in it.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
MCSection * getParent() const
unsigned getOrdinal() const
const MCSymbol * getAddSym() const
int64_t getConstant() const
const MCSymbol * getSubSym() const
bool isAbsolute() const
Is this an absolute (as opposed to relocatable) value.
bool doesSymbolRequireExternRelocation(const MCSymbol &S)
uint64_t getFragmentAddress(const MCAssembler &Asm, const MCFragment *Fragment) const
uint64_t getSectionAddress(const MCSection *Sec) const
void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, MachO::any_relocation_info &MRE)
const MCSymbol & findAliasedSymbol(const MCSymbol &Sym) const
const MCSymbol * getAtom(const MCSymbol &S) const
uint64_t getSymbolAddress(const MCSymbol &S) const
Target - Wrapper for Target specific information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ GENERIC_RELOC_LOCAL_SECTDIFF
@ X86_64_RELOC_SUBTRACTOR
@ S_ATTR_DEBUG
S_ATTR_DEBUG - A debug section.
@ reloc_riprel_4byte_movq_load_rex2
@ reloc_signed_4byte_relax
@ reloc_branch_4byte_pcrel
@ reloc_riprel_4byte_relax
@ reloc_riprel_4byte_relax_evex
@ reloc_riprel_4byte_relax_rex
@ reloc_riprel_4byte_movq_load
@ reloc_riprel_4byte_relax_rex2
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
static unsigned getFixupKindLog2Size(unsigned Kind)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ FK_Data_8
A eight-byte fixup.
@ FK_Data_1
A one-byte fixup.
@ FK_Data_4
A four-byte fixup.
@ FK_Data_2
A two-byte fixup.
std::unique_ptr< MCObjectTargetWriter > createX86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
Construct an X86 Mach-O object writer.
Definition X86MachObjectWriter.cpp:578