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