X86MachObjectWriter.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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/MCAsmLayout.h"
14#include "llvm/MC/MCAssembler.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCMachObjectWriter.h"
17#include "llvm/MC/MCSectionMachO.h"
18#include "llvm/MC/MCValue.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/Format.h"
21#include "llvm/Support/MachO.h"
22
23using namespace llvm;
24
25namespace {
26class X86MachObjectWriter : public MCMachObjectTargetWriter {
27  bool RecordScatteredRelocation(MachObjectWriter *Writer,
28                                 const MCAssembler &Asm,
29                                 const MCAsmLayout &Layout,
30                                 const MCFragment *Fragment,
31                                 const MCFixup &Fixup,
32                                 MCValue Target,
33                                 unsigned Log2Size,
34                                 uint64_t &FixedValue);
35  void RecordTLVPRelocation(MachObjectWriter *Writer,
36                            const MCAssembler &Asm,
37                            const MCAsmLayout &Layout,
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 MCAsmLayout &Layout,
46                              const MCFragment *Fragment,
47                              const MCFixup &Fixup,
48                              MCValue Target,
49                              uint64_t &FixedValue);
50  void RecordX86_64Relocation(MachObjectWriter *Writer,
51                              const MCAssembler &Asm,
52                              const MCAsmLayout &Layout,
53                              const MCFragment *Fragment,
54                              const MCFixup &Fixup,
55                              MCValue Target,
56                              uint64_t &FixedValue);
57public:
58  X86MachObjectWriter(bool Is64Bit, uint32_t CPUType,
59                      uint32_t CPUSubtype)
60    : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
61                               /*UseAggressiveSymbolFolding=*/Is64Bit) {}
62
63  void RecordRelocation(MachObjectWriter *Writer,
64                        const MCAssembler &Asm, const MCAsmLayout &Layout,
65                        const MCFragment *Fragment, const MCFixup &Fixup,
66                        MCValue Target, uint64_t &FixedValue) override {
67    if (Writer->is64Bit())
68      RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
69                             FixedValue);
70    else
71      RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
72                          FixedValue);
73  }
74};
75}
76
77static bool isFixupKindRIPRel(unsigned Kind) {
78  return Kind == X86::reloc_riprel_4byte ||
79    Kind == X86::reloc_riprel_4byte_movq_load;
80}
81
82static unsigned getFixupKindLog2Size(unsigned Kind) {
83  switch (Kind) {
84  default:
85    llvm_unreachable("invalid fixup kind!");
86  case FK_PCRel_1:
87  case FK_Data_1: return 0;
88  case FK_PCRel_2:
89  case FK_Data_2: return 1;
90  case FK_PCRel_4:
91    // FIXME: Remove these!!!
92  case X86::reloc_riprel_4byte:
93  case X86::reloc_riprel_4byte_movq_load:
94  case X86::reloc_signed_4byte:
95  case FK_Data_4: return 2;
96  case FK_Data_8: return 3;
97  }
98}
99
100void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
101                                                 const MCAssembler &Asm,
102                                                 const MCAsmLayout &Layout,
103                                                 const MCFragment *Fragment,
104                                                 const MCFixup &Fixup,
105                                                 MCValue Target,
106                                                 uint64_t &FixedValue) {
107  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
108  unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
109  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
110
111  // See <reloc.h>.
112  uint32_t FixupOffset =
113    Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
114  uint32_t FixupAddress =
115    Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
116  int64_t Value = 0;
117  unsigned Index = 0;
118  unsigned IsExtern = 0;
119  unsigned Type = 0;
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    Index = 0;
136
137    // FIXME: I believe this is broken, I don't think the linker can understand
138    // it. I think it would require a local relocation, but I'm not sure if that
139    // would work either. The official way to get an absolute PCrel relocation
140    // is to use an absolute symbol (which we don't support yet).
141    if (IsPCRel) {
142      IsExtern = 1;
143      Type = MachO::X86_64_RELOC_BRANCH;
144    }
145  } else if (Target.getSymB()) { // A - B + constant
146    const MCSymbol *A = &Target.getSymA()->getSymbol();
147    if (A->isTemporary())
148      A = &A->AliasedSymbol();
149    const MCSymbolData &A_SD = Asm.getSymbolData(*A);
150    const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
151
152    const MCSymbol *B = &Target.getSymB()->getSymbol();
153    if (B->isTemporary())
154      B = &B->AliasedSymbol();
155    const MCSymbolData &B_SD = Asm.getSymbolData(*B);
156    const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
157
158    // Neither symbol can be modified.
159    if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
160        Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
161      report_fatal_error("unsupported relocation of modified symbol", false);
162
163    // We don't support PCrel relocations of differences. Darwin 'as' doesn't
164    // implement most of these correctly.
165    if (IsPCRel)
166      report_fatal_error("unsupported pc-relative relocation of difference",
167                         false);
168
169    // The support for the situation where one or both of the symbols would
170    // require a local relocation is handled just like if the symbols were
171    // external.  This is certainly used in the case of debug sections where the
172    // section has only temporary symbols and thus the symbols don't have base
173    // symbols.  This is encoded using the section ordinal and non-extern
174    // relocation entries.
175
176    // Darwin 'as' doesn't emit correct relocations for this (it ends up with a
177    // single SIGNED relocation); reject it for now.  Except the case where both
178    // symbols don't have a base, equal but both NULL.
179    if (A_Base == B_Base && A_Base)
180      report_fatal_error("unsupported relocation with identical base", false);
181
182    // A subtraction expression where both symbols are undefined is a
183    // non-relocatable expression.
184    if (A->isUndefined() && B->isUndefined())
185      report_fatal_error("unsupported relocation with subtraction expression",
186                         false);
187
188    Value += Writer->getSymbolAddress(&A_SD, Layout) -
189      (!A_Base ? 0 : Writer->getSymbolAddress(A_Base, Layout));
190    Value -= Writer->getSymbolAddress(&B_SD, Layout) -
191      (!B_Base ? 0 : Writer->getSymbolAddress(B_Base, Layout));
192
193    if (A_Base) {
194      Index = A_Base->getIndex();
195      IsExtern = 1;
196    }
197    else {
198      Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
199      IsExtern = 0;
200    }
201    Type = MachO::X86_64_RELOC_UNSIGNED;
202
203    MachO::any_relocation_info MRE;
204    MRE.r_word0 = FixupOffset;
205    MRE.r_word1 = ((Index     <<  0) |
206                   (IsPCRel   << 24) |
207                   (Log2Size  << 25) |
208                   (IsExtern  << 27) |
209                   (Type      << 28));
210    Writer->addRelocation(Fragment->getParent(), MRE);
211
212    if (B_Base) {
213      Index = B_Base->getIndex();
214      IsExtern = 1;
215    }
216    else {
217      Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
218      IsExtern = 0;
219    }
220    Type = MachO::X86_64_RELOC_SUBTRACTOR;
221  } else {
222    const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
223    const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
224    const MCSymbolData *Base = Asm.getAtom(&SD);
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 = static_cast<const MCSectionMachO&>(
232        Fragment->getParent()->getSection());
233      if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
234        Base = 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 (Base) {
241      Index = Base->getIndex();
242      IsExtern = 1;
243
244      // Add the local offset, if needed.
245      if (Base != &SD)
246        Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
247    } else if (Symbol->isInSection() && !Symbol->isVariable()) {
248      // The index is the section ordinal (1-based).
249      Index = SD.getFragment()->getParent()->getOrdinal() + 1;
250      IsExtern = 0;
251      Value += Writer->getSymbolAddress(&SD, Layout);
252
253      if (IsPCRel)
254        Value -= FixupAddress + (1 << Log2Size);
255    } else if (Symbol->isVariable()) {
256      const MCExpr *Value = Symbol->getVariableValue();
257      int64_t Res;
258      bool isAbs = Value->EvaluateAsAbsolute(Res, Layout,
259                                             Writer->getSectionAddressMap());
260      if (isAbs) {
261        FixedValue = Res;
262        return;
263      } else {
264        report_fatal_error("unsupported relocation of variable '" +
265                           Symbol->getName() + "'", false);
266      }
267    } else {
268      report_fatal_error("unsupported relocation of undefined symbol '" +
269                         Symbol->getName() + "'", false);
270    }
271
272    MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
273    if (IsPCRel) {
274      if (IsRIPRel) {
275        if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
276          // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
277          // rewrite the movq to an leaq at link time if the symbol ends up in
278          // the same linkage unit.
279          if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
280            Type = MachO::X86_64_RELOC_GOT_LOAD;
281          else
282            Type = MachO::X86_64_RELOC_GOT;
283        }  else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
284          Type = MachO::X86_64_RELOC_TLV;
285        }  else if (Modifier != MCSymbolRefExpr::VK_None) {
286          report_fatal_error("unsupported symbol modifier in relocation",
287                             false);
288        } else {
289          Type = MachO::X86_64_RELOC_SIGNED;
290
291          // The Darwin x86_64 relocation format has a problem where it cannot
292          // encode an address (L<foo> + <constant>) which is outside the atom
293          // containing L<foo>. Generally, this shouldn't occur but it does
294          // happen when we have a RIPrel instruction with data following the
295          // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
296          // adjustment Darwin x86_64 uses, the offset is still negative and the
297          // linker has no way to recognize this.
298          //
299          // To work around this, Darwin uses several special relocation types
300          // to indicate the offsets. However, the specification or
301          // implementation of these seems to also be incomplete; they should
302          // adjust the addend as well based on the actual encoded instruction
303          // (the additional bias), but instead appear to just look at the final
304          // offset.
305          switch (-(Target.getConstant() + (1LL << Log2Size))) {
306          case 1: Type = MachO::X86_64_RELOC_SIGNED_1; break;
307          case 2: Type = MachO::X86_64_RELOC_SIGNED_2; break;
308          case 4: Type = MachO::X86_64_RELOC_SIGNED_4; break;
309          }
310        }
311      } else {
312        if (Modifier != MCSymbolRefExpr::VK_None)
313          report_fatal_error("unsupported symbol modifier in branch "
314                             "relocation", false);
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        report_fatal_error("TLVP symbol modifier should have been rip-rel",
330                           false);
331      } else if (Modifier != MCSymbolRefExpr::VK_None)
332        report_fatal_error("unsupported symbol modifier in relocation", false);
333      else {
334        Type = MachO::X86_64_RELOC_UNSIGNED;
335        unsigned Kind = Fixup.getKind();
336        if (Kind == X86::reloc_signed_4byte)
337          report_fatal_error("32-bit absolute addressing is not supported in "
338                             "64-bit mode", false);
339      }
340    }
341  }
342
343  // x86_64 always writes custom values into the fixups.
344  FixedValue = Value;
345
346  // struct relocation_info (8 bytes)
347  MachO::any_relocation_info MRE;
348  MRE.r_word0 = FixupOffset;
349  MRE.r_word1 = ((Index     <<  0) |
350                 (IsPCRel   << 24) |
351                 (Log2Size  << 25) |
352                 (IsExtern  << 27) |
353                 (Type      << 28));
354  Writer->addRelocation(Fragment->getParent(), MRE);
355}
356
357bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
358                                                    const MCAssembler &Asm,
359                                                    const MCAsmLayout &Layout,
360                                                    const MCFragment *Fragment,
361                                                    const MCFixup &Fixup,
362                                                    MCValue Target,
363                                                    unsigned Log2Size,
364                                                    uint64_t &FixedValue) {
365  uint64_t OriginalFixedValue = FixedValue;
366  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
367  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
368  unsigned Type = MachO::GENERIC_RELOC_VANILLA;
369
370  // See <reloc.h>.
371  const MCSymbol *A = &Target.getSymA()->getSymbol();
372  const MCSymbolData *A_SD = &Asm.getSymbolData(*A);
373
374  if (!A_SD->getFragment())
375    report_fatal_error("symbol '" + A->getName() +
376                       "' can not be undefined in a subtraction expression",
377                       false);
378
379  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
380  uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
381  FixedValue += SecAddr;
382  uint32_t Value2 = 0;
383
384  if (const MCSymbolRefExpr *B = Target.getSymB()) {
385    const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
386
387    if (!B_SD->getFragment())
388      report_fatal_error("symbol '" + B->getSymbol().getName() +
389                         "' can not be undefined in a subtraction expression",
390                         false);
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_SD->isExternal() ? (unsigned)MachO::GENERIC_RELOC_SECTDIFF :
398      (unsigned)MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
399    Value2 = Writer->getSymbolAddress(B_SD, Layout);
400    FixedValue -= Writer->getSectionAddress(B_SD->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().FatalError(Fixup.getLoc(),
412                         Twine("Section too large, can't encode "
413                                "r_address (") + Buffer +
414                         ") into 24 bits of scattered "
415                         "relocation entry.");
416      llvm_unreachable("fatal error returned?!");
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(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(Fragment->getParent(), MRE);
449  return true;
450}
451
452void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
453                                               const MCAssembler &Asm,
454                                               const MCAsmLayout &Layout,
455                                               const MCFragment *Fragment,
456                                               const MCFixup &Fixup,
457                                               MCValue Target,
458                                               uint64_t &FixedValue) {
459  assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
460         !is64Bit() &&
461         "Should only be called with a 32-bit TLVP relocation!");
462
463  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
464  uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
465  unsigned IsPCRel = 0;
466
467  // Get the symbol data.
468  const MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
469  unsigned Index = SD_A->getIndex();
470
471  // We're only going to have a second symbol in pic mode and it'll be a
472  // subtraction from the picbase. For 32-bit pic the addend is the difference
473  // between the picbase and the next address.  For 32-bit static the addend is
474  // zero.
475  if (Target.getSymB()) {
476    // If this is a subtraction then we're pcrel.
477    uint32_t FixupAddress =
478      Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
479    const MCSymbolData *SD_B =
480        &Asm.getSymbolData(Target.getSymB()->getSymbol());
481    IsPCRel = 1;
482    FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) +
483                  Target.getConstant());
484    FixedValue += 1ULL << Log2Size;
485  } else {
486    FixedValue = 0;
487  }
488
489  // struct relocation_info (8 bytes)
490  MachO::any_relocation_info MRE;
491  MRE.r_word0 = Value;
492  MRE.r_word1 = ((Index                    <<  0) |
493                 (IsPCRel                  << 24) |
494                 (Log2Size                 << 25) |
495                 (1                        << 27) | // r_extern
496                 (MachO::GENERIC_RELOC_TLV << 28)); // r_type
497  Writer->addRelocation(Fragment->getParent(), MRE);
498}
499
500void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
501                                              const MCAssembler &Asm,
502                                              const MCAsmLayout &Layout,
503                                              const MCFragment *Fragment,
504                                              const MCFixup &Fixup,
505                                              MCValue Target,
506                                              uint64_t &FixedValue) {
507  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
508  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
509
510  // If this is a 32-bit TLVP reloc it's handled a bit differently.
511  if (Target.getSymA() &&
512      Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
513    RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
514                         FixedValue);
515    return;
516  }
517
518  // If this is a difference or a defined symbol plus an offset, then we need a
519  // scattered relocation entry. Differences always require scattered
520  // relocations.
521  if (Target.getSymB()) {
522    RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
523                              Target, Log2Size, FixedValue);
524    return;
525  }
526
527  // Get the symbol data, if any.
528  const MCSymbolData *SD = nullptr;
529  if (Target.getSymA())
530    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
531
532  // If this is an internal relocation with an offset, it also needs a scattered
533  // relocation entry.
534  uint32_t Offset = Target.getConstant();
535  if (IsPCRel)
536    Offset += 1 << Log2Size;
537  // Try to record the scattered relocation if needed. Fall back to non
538  // scattered if necessary (see comments in RecordScatteredRelocation()
539  // for details).
540  if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) &&
541      RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
542                                Target, Log2Size, FixedValue))
543    return;
544
545  // See <reloc.h>.
546  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
547  unsigned Index = 0;
548  unsigned IsExtern = 0;
549  unsigned Type = 0;
550
551  if (Target.isAbsolute()) { // constant
552    // SymbolNum of 0 indicates the absolute section.
553    //
554    // FIXME: Currently, these are never generated (see code below). I cannot
555    // find a case where they are actually emitted.
556    Type = MachO::GENERIC_RELOC_VANILLA;
557  } else {
558    // Resolve constant variables.
559    if (SD->getSymbol().isVariable()) {
560      int64_t Res;
561      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
562            Res, Layout, Writer->getSectionAddressMap())) {
563        FixedValue = Res;
564        return;
565      }
566    }
567
568    // Check whether we need an external or internal relocation.
569    if (Writer->doesSymbolRequireExternRelocation(SD)) {
570      IsExtern = 1;
571      Index = SD->getIndex();
572      // For external relocations, make sure to offset the fixup value to
573      // compensate for the addend of the symbol address, if it was
574      // undefined. This occurs with weak definitions, for example.
575      if (!SD->Symbol->isUndefined())
576        FixedValue -= Layout.getSymbolOffset(SD);
577    } else {
578      // The index is the section ordinal (1-based).
579      const MCSectionData &SymSD = Asm.getSectionData(
580        SD->getSymbol().getSection());
581      Index = SymSD.getOrdinal() + 1;
582      FixedValue += Writer->getSectionAddress(&SymSD);
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 = ((Index     <<  0) |
594                 (IsPCRel   << 24) |
595                 (Log2Size  << 25) |
596                 (IsExtern  << 27) |
597                 (Type      << 28));
598  Writer->addRelocation(Fragment->getParent(), MRE);
599}
600
601MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS,
602                                                bool Is64Bit,
603                                                uint32_t CPUType,
604                                                uint32_t CPUSubtype) {
605  return createMachObjectWriter(new X86MachObjectWriter(Is64Bit,
606                                                        CPUType,
607                                                        CPUSubtype),
608                                OS, /*IsLittleEndian=*/true);
609}
610