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