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