LLVM API Documentation

X86MachObjectWriter.cpp
Go to the documentation of this file.
00001 //===-- X86MachObjectWriter.cpp - X86 Mach-O Writer -----------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "MCTargetDesc/X86MCTargetDesc.h"
00011 #include "MCTargetDesc/X86FixupKinds.h"
00012 #include "llvm/ADT/Twine.h"
00013 #include "llvm/MC/MCAsmLayout.h"
00014 #include "llvm/MC/MCAssembler.h"
00015 #include "llvm/MC/MCContext.h"
00016 #include "llvm/MC/MCMachObjectWriter.h"
00017 #include "llvm/MC/MCSectionMachO.h"
00018 #include "llvm/MC/MCValue.h"
00019 #include "llvm/Support/ErrorHandling.h"
00020 #include "llvm/Support/Format.h"
00021 #include "llvm/Support/MachO.h"
00022 
00023 using namespace llvm;
00024 
00025 namespace {
00026 class X86MachObjectWriter : public MCMachObjectTargetWriter {
00027   bool RecordScatteredRelocation(MachObjectWriter *Writer,
00028                                  const MCAssembler &Asm,
00029                                  const MCAsmLayout &Layout,
00030                                  const MCFragment *Fragment,
00031                                  const MCFixup &Fixup,
00032                                  MCValue Target,
00033                                  unsigned Log2Size,
00034                                  uint64_t &FixedValue);
00035   void RecordTLVPRelocation(MachObjectWriter *Writer,
00036                             const MCAssembler &Asm,
00037                             const MCAsmLayout &Layout,
00038                             const MCFragment *Fragment,
00039                             const MCFixup &Fixup,
00040                             MCValue Target,
00041                             uint64_t &FixedValue);
00042 
00043   void RecordX86Relocation(MachObjectWriter *Writer,
00044                               const MCAssembler &Asm,
00045                               const MCAsmLayout &Layout,
00046                               const MCFragment *Fragment,
00047                               const MCFixup &Fixup,
00048                               MCValue Target,
00049                               uint64_t &FixedValue);
00050   void RecordX86_64Relocation(MachObjectWriter *Writer,
00051                               const MCAssembler &Asm,
00052                               const MCAsmLayout &Layout,
00053                               const MCFragment *Fragment,
00054                               const MCFixup &Fixup,
00055                               MCValue Target,
00056                               uint64_t &FixedValue);
00057 public:
00058   X86MachObjectWriter(bool Is64Bit, uint32_t CPUType,
00059                       uint32_t CPUSubtype)
00060     : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
00061                                /*UseAggressiveSymbolFolding=*/Is64Bit) {}
00062 
00063   void RecordRelocation(MachObjectWriter *Writer,
00064                         const MCAssembler &Asm, const MCAsmLayout &Layout,
00065                         const MCFragment *Fragment, const MCFixup &Fixup,
00066                         MCValue Target, uint64_t &FixedValue) override {
00067     if (Writer->is64Bit())
00068       RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
00069                              FixedValue);
00070     else
00071       RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target,
00072                           FixedValue);
00073   }
00074 };
00075 }
00076 
00077 static bool isFixupKindRIPRel(unsigned Kind) {
00078   return Kind == X86::reloc_riprel_4byte ||
00079     Kind == X86::reloc_riprel_4byte_movq_load;
00080 }
00081 
00082 static unsigned getFixupKindLog2Size(unsigned Kind) {
00083   switch (Kind) {
00084   default:
00085     llvm_unreachable("invalid fixup kind!");
00086   case FK_PCRel_1:
00087   case FK_Data_1: return 0;
00088   case FK_PCRel_2:
00089   case FK_Data_2: return 1;
00090   case FK_PCRel_4:
00091     // FIXME: Remove these!!!
00092   case X86::reloc_riprel_4byte:
00093   case X86::reloc_riprel_4byte_movq_load:
00094   case X86::reloc_signed_4byte:
00095   case FK_Data_4: return 2;
00096   case FK_Data_8: return 3;
00097   }
00098 }
00099 
00100 void X86MachObjectWriter::RecordX86_64Relocation(MachObjectWriter *Writer,
00101                                                  const MCAssembler &Asm,
00102                                                  const MCAsmLayout &Layout,
00103                                                  const MCFragment *Fragment,
00104                                                  const MCFixup &Fixup,
00105                                                  MCValue Target,
00106                                                  uint64_t &FixedValue) {
00107   unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
00108   unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
00109   unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
00110 
00111   // See <reloc.h>.
00112   uint32_t FixupOffset =
00113     Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
00114   uint32_t FixupAddress =
00115     Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
00116   int64_t Value = 0;
00117   unsigned Index = 0;
00118   unsigned IsExtern = 0;
00119   unsigned Type = 0;
00120 
00121   Value = Target.getConstant();
00122 
00123   if (IsPCRel) {
00124     // Compensate for the relocation offset, Darwin x86_64 relocations only have
00125     // the addend and appear to have attempted to define it to be the actual
00126     // expression addend without the PCrel bias. However, instructions with data
00127     // following the relocation are not accommodated for (see comment below
00128     // regarding SIGNED{1,2,4}), so it isn't exactly that either.
00129     Value += 1LL << Log2Size;
00130   }
00131 
00132   if (Target.isAbsolute()) { // constant
00133     // SymbolNum of 0 indicates the absolute section.
00134     Type = MachO::X86_64_RELOC_UNSIGNED;
00135     Index = 0;
00136 
00137     // FIXME: I believe this is broken, I don't think the linker can understand
00138     // it. I think it would require a local relocation, but I'm not sure if that
00139     // would work either. The official way to get an absolute PCrel relocation
00140     // is to use an absolute symbol (which we don't support yet).
00141     if (IsPCRel) {
00142       IsExtern = 1;
00143       Type = MachO::X86_64_RELOC_BRANCH;
00144     }
00145   } else if (Target.getSymB()) { // A - B + constant
00146     const MCSymbol *A = &Target.getSymA()->getSymbol();
00147     if (A->isTemporary())
00148       A = &A->AliasedSymbol();
00149     const MCSymbolData &A_SD = Asm.getSymbolData(*A);
00150     const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
00151 
00152     const MCSymbol *B = &Target.getSymB()->getSymbol();
00153     if (B->isTemporary())
00154       B = &B->AliasedSymbol();
00155     const MCSymbolData &B_SD = Asm.getSymbolData(*B);
00156     const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
00157 
00158     // Neither symbol can be modified.
00159     if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
00160         Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
00161       report_fatal_error("unsupported relocation of modified symbol", false);
00162 
00163     // We don't support PCrel relocations of differences. Darwin 'as' doesn't
00164     // implement most of these correctly.
00165     if (IsPCRel)
00166       report_fatal_error("unsupported pc-relative relocation of difference",
00167                          false);
00168 
00169     // The support for the situation where one or both of the symbols would
00170     // require a local relocation is handled just like if the symbols were
00171     // external.  This is certainly used in the case of debug sections where the
00172     // section has only temporary symbols and thus the symbols don't have base
00173     // symbols.  This is encoded using the section ordinal and non-extern
00174     // relocation entries.
00175 
00176     // Darwin 'as' doesn't emit correct relocations for this (it ends up with a
00177     // single SIGNED relocation); reject it for now.  Except the case where both
00178     // symbols don't have a base, equal but both NULL.
00179     if (A_Base == B_Base && A_Base)
00180       report_fatal_error("unsupported relocation with identical base", false);
00181 
00182     // A subtraction expression where both symbols are undefined is a
00183     // non-relocatable expression.
00184     if (A->isUndefined() && B->isUndefined())
00185       report_fatal_error("unsupported relocation with subtraction expression",
00186                          false);
00187 
00188     Value += Writer->getSymbolAddress(&A_SD, Layout) -
00189       (!A_Base ? 0 : Writer->getSymbolAddress(A_Base, Layout));
00190     Value -= Writer->getSymbolAddress(&B_SD, Layout) -
00191       (!B_Base ? 0 : Writer->getSymbolAddress(B_Base, Layout));
00192 
00193     if (A_Base) {
00194       Index = A_Base->getIndex();
00195       IsExtern = 1;
00196     }
00197     else {
00198       Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
00199       IsExtern = 0;
00200     }
00201     Type = MachO::X86_64_RELOC_UNSIGNED;
00202 
00203     MachO::any_relocation_info MRE;
00204     MRE.r_word0 = FixupOffset;
00205     MRE.r_word1 = ((Index     <<  0) |
00206                    (IsPCRel   << 24) |
00207                    (Log2Size  << 25) |
00208                    (IsExtern  << 27) |
00209                    (Type      << 28));
00210     Writer->addRelocation(Fragment->getParent(), MRE);
00211 
00212     if (B_Base) {
00213       Index = B_Base->getIndex();
00214       IsExtern = 1;
00215     }
00216     else {
00217       Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
00218       IsExtern = 0;
00219     }
00220     Type = MachO::X86_64_RELOC_SUBTRACTOR;
00221   } else {
00222     const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
00223     const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
00224     const MCSymbolData *Base = Asm.getAtom(&SD);
00225 
00226     // Relocations inside debug sections always use local relocations when
00227     // possible. This seems to be done because the debugger doesn't fully
00228     // understand x86_64 relocation entries, and expects to find values that
00229     // have already been fixed up.
00230     if (Symbol->isInSection()) {
00231       const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
00232         Fragment->getParent()->getSection());
00233       if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
00234         Base = nullptr;
00235     }
00236 
00237     // x86_64 almost always uses external relocations, except when there is no
00238     // symbol to use as a base address (a local symbol with no preceding
00239     // non-local symbol).
00240     if (Base) {
00241       Index = Base->getIndex();
00242       IsExtern = 1;
00243 
00244       // Add the local offset, if needed.
00245       if (Base != &SD)
00246         Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
00247     } else if (Symbol->isInSection() && !Symbol->isVariable()) {
00248       // The index is the section ordinal (1-based).
00249       Index = SD.getFragment()->getParent()->getOrdinal() + 1;
00250       IsExtern = 0;
00251       Value += Writer->getSymbolAddress(&SD, Layout);
00252 
00253       if (IsPCRel)
00254         Value -= FixupAddress + (1 << Log2Size);
00255     } else if (Symbol->isVariable()) {
00256       const MCExpr *Value = Symbol->getVariableValue();
00257       int64_t Res;
00258       bool isAbs = Value->EvaluateAsAbsolute(Res, Layout,
00259                                              Writer->getSectionAddressMap());
00260       if (isAbs) {
00261         FixedValue = Res;
00262         return;
00263       } else {
00264         report_fatal_error("unsupported relocation of variable '" +
00265                            Symbol->getName() + "'", false);
00266       }
00267     } else {
00268       report_fatal_error("unsupported relocation of undefined symbol '" +
00269                          Symbol->getName() + "'", false);
00270     }
00271 
00272     MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
00273     if (IsPCRel) {
00274       if (IsRIPRel) {
00275         if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
00276           // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
00277           // rewrite the movq to an leaq at link time if the symbol ends up in
00278           // the same linkage unit.
00279           if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
00280             Type = MachO::X86_64_RELOC_GOT_LOAD;
00281           else
00282             Type = MachO::X86_64_RELOC_GOT;
00283         }  else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
00284           Type = MachO::X86_64_RELOC_TLV;
00285         }  else if (Modifier != MCSymbolRefExpr::VK_None) {
00286           report_fatal_error("unsupported symbol modifier in relocation",
00287                              false);
00288         } else {
00289           Type = MachO::X86_64_RELOC_SIGNED;
00290 
00291           // The Darwin x86_64 relocation format has a problem where it cannot
00292           // encode an address (L<foo> + <constant>) which is outside the atom
00293           // containing L<foo>. Generally, this shouldn't occur but it does
00294           // happen when we have a RIPrel instruction with data following the
00295           // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
00296           // adjustment Darwin x86_64 uses, the offset is still negative and the
00297           // linker has no way to recognize this.
00298           //
00299           // To work around this, Darwin uses several special relocation types
00300           // to indicate the offsets. However, the specification or
00301           // implementation of these seems to also be incomplete; they should
00302           // adjust the addend as well based on the actual encoded instruction
00303           // (the additional bias), but instead appear to just look at the final
00304           // offset.
00305           switch (-(Target.getConstant() + (1LL << Log2Size))) {
00306           case 1: Type = MachO::X86_64_RELOC_SIGNED_1; break;
00307           case 2: Type = MachO::X86_64_RELOC_SIGNED_2; break;
00308           case 4: Type = MachO::X86_64_RELOC_SIGNED_4; break;
00309           }
00310         }
00311       } else {
00312         if (Modifier != MCSymbolRefExpr::VK_None)
00313           report_fatal_error("unsupported symbol modifier in branch "
00314                              "relocation", false);
00315 
00316         Type = MachO::X86_64_RELOC_BRANCH;
00317       }
00318     } else {
00319       if (Modifier == MCSymbolRefExpr::VK_GOT) {
00320         Type = MachO::X86_64_RELOC_GOT;
00321       } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
00322         // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which
00323         // case all we do is set the PCrel bit in the relocation entry; this is
00324         // used with exception handling, for example. The source is required to
00325         // include any necessary offset directly.
00326         Type = MachO::X86_64_RELOC_GOT;
00327         IsPCRel = 1;
00328       } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
00329         report_fatal_error("TLVP symbol modifier should have been rip-rel",
00330                            false);
00331       } else if (Modifier != MCSymbolRefExpr::VK_None)
00332         report_fatal_error("unsupported symbol modifier in relocation", false);
00333       else {
00334         Type = MachO::X86_64_RELOC_UNSIGNED;
00335         unsigned Kind = Fixup.getKind();
00336         if (Kind == X86::reloc_signed_4byte)
00337           report_fatal_error("32-bit absolute addressing is not supported in "
00338                              "64-bit mode", false);
00339       }
00340     }
00341   }
00342 
00343   // x86_64 always writes custom values into the fixups.
00344   FixedValue = Value;
00345 
00346   // struct relocation_info (8 bytes)
00347   MachO::any_relocation_info MRE;
00348   MRE.r_word0 = FixupOffset;
00349   MRE.r_word1 = ((Index     <<  0) |
00350                  (IsPCRel   << 24) |
00351                  (Log2Size  << 25) |
00352                  (IsExtern  << 27) |
00353                  (Type      << 28));
00354   Writer->addRelocation(Fragment->getParent(), MRE);
00355 }
00356 
00357 bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
00358                                                     const MCAssembler &Asm,
00359                                                     const MCAsmLayout &Layout,
00360                                                     const MCFragment *Fragment,
00361                                                     const MCFixup &Fixup,
00362                                                     MCValue Target,
00363                                                     unsigned Log2Size,
00364                                                     uint64_t &FixedValue) {
00365   uint64_t OriginalFixedValue = FixedValue;
00366   uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
00367   unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
00368   unsigned Type = MachO::GENERIC_RELOC_VANILLA;
00369 
00370   // See <reloc.h>.
00371   const MCSymbol *A = &Target.getSymA()->getSymbol();
00372   const MCSymbolData *A_SD = &Asm.getSymbolData(*A);
00373 
00374   if (!A_SD->getFragment())
00375     report_fatal_error("symbol '" + A->getName() +
00376                        "' can not be undefined in a subtraction expression",
00377                        false);
00378 
00379   uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
00380   uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
00381   FixedValue += SecAddr;
00382   uint32_t Value2 = 0;
00383 
00384   if (const MCSymbolRefExpr *B = Target.getSymB()) {
00385     const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
00386 
00387     if (!B_SD->getFragment())
00388       report_fatal_error("symbol '" + B->getSymbol().getName() +
00389                          "' can not be undefined in a subtraction expression",
00390                          false);
00391 
00392     // Select the appropriate difference relocation type.
00393     //
00394     // Note that there is no longer any semantic difference between these two
00395     // relocation types from the linkers point of view, this is done solely for
00396     // pedantic compatibility with 'as'.
00397     Type = A_SD->isExternal() ? (unsigned)MachO::GENERIC_RELOC_SECTDIFF :
00398       (unsigned)MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
00399     Value2 = Writer->getSymbolAddress(B_SD, Layout);
00400     FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
00401   }
00402 
00403   // Relocations are written out in reverse order, so the PAIR comes first.
00404   if (Type == MachO::GENERIC_RELOC_SECTDIFF ||
00405       Type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
00406     // If the offset is too large to fit in a scattered relocation,
00407     // we're hosed. It's an unfortunate limitation of the MachO format.
00408     if (FixupOffset > 0xffffff) {
00409       char Buffer[32];
00410       format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
00411       Asm.getContext().FatalError(Fixup.getLoc(),
00412                          Twine("Section too large, can't encode "
00413                                 "r_address (") + Buffer +
00414                          ") into 24 bits of scattered "
00415                          "relocation entry.");
00416       llvm_unreachable("fatal error returned?!");
00417     }
00418 
00419     MachO::any_relocation_info MRE;
00420     MRE.r_word0 = ((0                         <<  0) | // r_address
00421                    (MachO::GENERIC_RELOC_PAIR << 24) | // r_type
00422                    (Log2Size                  << 28) |
00423                    (IsPCRel                   << 30) |
00424                    MachO::R_SCATTERED);
00425     MRE.r_word1 = Value2;
00426     Writer->addRelocation(Fragment->getParent(), MRE);
00427   } else {
00428     // If the offset is more than 24-bits, it won't fit in a scattered
00429     // relocation offset field, so we fall back to using a non-scattered
00430     // relocation. This is a bit risky, as if the offset reaches out of
00431     // the block and the linker is doing scattered loading on this
00432     // symbol, things can go badly.
00433     //
00434     // Required for 'as' compatibility.
00435     if (FixupOffset > 0xffffff) {
00436       FixedValue = OriginalFixedValue;
00437       return false;
00438     }
00439   }
00440 
00441   MachO::any_relocation_info MRE;
00442   MRE.r_word0 = ((FixupOffset <<  0) |
00443                  (Type        << 24) |
00444                  (Log2Size    << 28) |
00445                  (IsPCRel     << 30) |
00446                  MachO::R_SCATTERED);
00447   MRE.r_word1 = Value;
00448   Writer->addRelocation(Fragment->getParent(), MRE);
00449   return true;
00450 }
00451 
00452 void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
00453                                                const MCAssembler &Asm,
00454                                                const MCAsmLayout &Layout,
00455                                                const MCFragment *Fragment,
00456                                                const MCFixup &Fixup,
00457                                                MCValue Target,
00458                                                uint64_t &FixedValue) {
00459   assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
00460          !is64Bit() &&
00461          "Should only be called with a 32-bit TLVP relocation!");
00462 
00463   unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
00464   uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
00465   unsigned IsPCRel = 0;
00466 
00467   // Get the symbol data.
00468   const MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
00469   unsigned Index = SD_A->getIndex();
00470 
00471   // We're only going to have a second symbol in pic mode and it'll be a
00472   // subtraction from the picbase. For 32-bit pic the addend is the difference
00473   // between the picbase and the next address.  For 32-bit static the addend is
00474   // zero.
00475   if (Target.getSymB()) {
00476     // If this is a subtraction then we're pcrel.
00477     uint32_t FixupAddress =
00478       Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
00479     const MCSymbolData *SD_B =
00480         &Asm.getSymbolData(Target.getSymB()->getSymbol());
00481     IsPCRel = 1;
00482     FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) +
00483                   Target.getConstant());
00484     FixedValue += 1ULL << Log2Size;
00485   } else {
00486     FixedValue = 0;
00487   }
00488 
00489   // struct relocation_info (8 bytes)
00490   MachO::any_relocation_info MRE;
00491   MRE.r_word0 = Value;
00492   MRE.r_word1 = ((Index                    <<  0) |
00493                  (IsPCRel                  << 24) |
00494                  (Log2Size                 << 25) |
00495                  (1                        << 27) | // r_extern
00496                  (MachO::GENERIC_RELOC_TLV << 28)); // r_type
00497   Writer->addRelocation(Fragment->getParent(), MRE);
00498 }
00499 
00500 void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
00501                                               const MCAssembler &Asm,
00502                                               const MCAsmLayout &Layout,
00503                                               const MCFragment *Fragment,
00504                                               const MCFixup &Fixup,
00505                                               MCValue Target,
00506                                               uint64_t &FixedValue) {
00507   unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
00508   unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
00509 
00510   // If this is a 32-bit TLVP reloc it's handled a bit differently.
00511   if (Target.getSymA() &&
00512       Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
00513     RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
00514                          FixedValue);
00515     return;
00516   }
00517 
00518   // If this is a difference or a defined symbol plus an offset, then we need a
00519   // scattered relocation entry. Differences always require scattered
00520   // relocations.
00521   if (Target.getSymB()) {
00522     RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
00523                               Target, Log2Size, FixedValue);
00524     return;
00525   }
00526 
00527   // Get the symbol data, if any.
00528   const MCSymbolData *SD = nullptr;
00529   if (Target.getSymA())
00530     SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
00531 
00532   // If this is an internal relocation with an offset, it also needs a scattered
00533   // relocation entry.
00534   uint32_t Offset = Target.getConstant();
00535   if (IsPCRel)
00536     Offset += 1 << Log2Size;
00537   // Try to record the scattered relocation if needed. Fall back to non
00538   // scattered if necessary (see comments in RecordScatteredRelocation()
00539   // for details).
00540   if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) &&
00541       RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
00542                                 Target, Log2Size, FixedValue))
00543     return;
00544 
00545   // See <reloc.h>.
00546   uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
00547   unsigned Index = 0;
00548   unsigned IsExtern = 0;
00549   unsigned Type = 0;
00550 
00551   if (Target.isAbsolute()) { // constant
00552     // SymbolNum of 0 indicates the absolute section.
00553     //
00554     // FIXME: Currently, these are never generated (see code below). I cannot
00555     // find a case where they are actually emitted.
00556     Type = MachO::GENERIC_RELOC_VANILLA;
00557   } else {
00558     // Resolve constant variables.
00559     if (SD->getSymbol().isVariable()) {
00560       int64_t Res;
00561       if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
00562             Res, Layout, Writer->getSectionAddressMap())) {
00563         FixedValue = Res;
00564         return;
00565       }
00566     }
00567 
00568     // Check whether we need an external or internal relocation.
00569     if (Writer->doesSymbolRequireExternRelocation(SD)) {
00570       IsExtern = 1;
00571       Index = SD->getIndex();
00572       // For external relocations, make sure to offset the fixup value to
00573       // compensate for the addend of the symbol address, if it was
00574       // undefined. This occurs with weak definitions, for example.
00575       if (!SD->Symbol->isUndefined())
00576         FixedValue -= Layout.getSymbolOffset(SD);
00577     } else {
00578       // The index is the section ordinal (1-based).
00579       const MCSectionData &SymSD = Asm.getSectionData(
00580         SD->getSymbol().getSection());
00581       Index = SymSD.getOrdinal() + 1;
00582       FixedValue += Writer->getSectionAddress(&SymSD);
00583     }
00584     if (IsPCRel)
00585       FixedValue -= Writer->getSectionAddress(Fragment->getParent());
00586 
00587     Type = MachO::GENERIC_RELOC_VANILLA;
00588   }
00589 
00590   // struct relocation_info (8 bytes)
00591   MachO::any_relocation_info MRE;
00592   MRE.r_word0 = FixupOffset;
00593   MRE.r_word1 = ((Index     <<  0) |
00594                  (IsPCRel   << 24) |
00595                  (Log2Size  << 25) |
00596                  (IsExtern  << 27) |
00597                  (Type      << 28));
00598   Writer->addRelocation(Fragment->getParent(), MRE);
00599 }
00600 
00601 MCObjectWriter *llvm::createX86MachObjectWriter(raw_ostream &OS,
00602                                                 bool Is64Bit,
00603                                                 uint32_t CPUType,
00604                                                 uint32_t CPUSubtype) {
00605   return createMachObjectWriter(new X86MachObjectWriter(Is64Bit,
00606                                                         CPUType,
00607                                                         CPUSubtype),
00608                                 OS, /*IsLittleEndian=*/true);
00609 }