Coverage Report

Created: 2017-10-03 07:32

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