LCOV - code coverage report
Current view: top level - lib/MC - MachObjectWriter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 421 430 97.9 %
Date: 2018-02-19 03:08:00 Functions: 26 26 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- lib/MC/MachObjectWriter.cpp - Mach-O File 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 "llvm/ADT/DenseMap.h"
      11             : #include "llvm/ADT/Twine.h"
      12             : #include "llvm/ADT/iterator_range.h"
      13             : #include "llvm/BinaryFormat/MachO.h"
      14             : #include "llvm/MC/MCAsmBackend.h"
      15             : #include "llvm/MC/MCAsmLayout.h"
      16             : #include "llvm/MC/MCAssembler.h"
      17             : #include "llvm/MC/MCDirectives.h"
      18             : #include "llvm/MC/MCExpr.h"
      19             : #include "llvm/MC/MCFixupKindInfo.h"
      20             : #include "llvm/MC/MCFragment.h"
      21             : #include "llvm/MC/MCMachObjectWriter.h"
      22             : #include "llvm/MC/MCObjectWriter.h"
      23             : #include "llvm/MC/MCSection.h"
      24             : #include "llvm/MC/MCSectionMachO.h"
      25             : #include "llvm/MC/MCSymbol.h"
      26             : #include "llvm/MC/MCSymbolMachO.h"
      27             : #include "llvm/MC/MCValue.h"
      28             : #include "llvm/Support/Casting.h"
      29             : #include "llvm/Support/Debug.h"
      30             : #include "llvm/Support/ErrorHandling.h"
      31             : #include "llvm/Support/MathExtras.h"
      32             : #include "llvm/Support/raw_ostream.h"
      33             : #include <algorithm>
      34             : #include <cassert>
      35             : #include <cstdint>
      36             : #include <string>
      37             : #include <utility>
      38             : #include <vector>
      39             : 
      40             : using namespace llvm;
      41             : 
      42             : #define DEBUG_TYPE "mc"
      43             : 
      44         275 : void MachObjectWriter::reset() {
      45         275 :   Relocations.clear();
      46         275 :   IndirectSymBase.clear();
      47         275 :   StringTable.clear();
      48             :   LocalSymbolData.clear();
      49             :   ExternalSymbolData.clear();
      50             :   UndefinedSymbolData.clear();
      51             :   MCObjectWriter::reset();
      52         275 : }
      53             : 
      54        1488 : bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) {
      55             :   // Undefined symbols are always extern.
      56        1488 :   if (S.isUndefined())
      57             :     return true;
      58             : 
      59             :   // References to weak definitions require external relocation entries; the
      60             :   // definition may not always be the one in the same object file.
      61         274 :   if (cast<MCSymbolMachO>(S).isWeakDefinition())
      62             :     return true;
      63             : 
      64             :   // Otherwise, we can use an internal relocation.
      65         270 :   return false;
      66             : }
      67             : 
      68        1677 : bool MachObjectWriter::
      69             : MachSymbolData::operator<(const MachSymbolData &RHS) const {
      70        5031 :   return Symbol->getName() < RHS.Symbol->getName();
      71             : }
      72             : 
      73        3466 : bool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
      74        3466 :   const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo(
      75        3466 :     (MCFixupKind) Kind);
      76             : 
      77        3466 :   return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
      78             : }
      79             : 
      80        1481 : uint64_t MachObjectWriter::getFragmentAddress(const MCFragment *Fragment,
      81             :                                               const MCAsmLayout &Layout) const {
      82        1481 :   return getSectionAddress(Fragment->getParent()) +
      83        1481 :          Layout.getFragmentOffset(Fragment);
      84             : }
      85             : 
      86        2422 : uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S,
      87             :                                             const MCAsmLayout &Layout) const {
      88             :   // If this is a variable, then recursively evaluate now.
      89        2422 :   if (S.isVariable()) {
      90             :     if (const MCConstantExpr *C =
      91             :           dyn_cast<const MCConstantExpr>(S.getVariableValue()))
      92           4 :       return C->getValue();
      93             : 
      94          36 :     MCValue Target;
      95          36 :     if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Layout, nullptr))
      96           0 :       report_fatal_error("unable to evaluate offset for variable '" +
      97           0 :                          S.getName() + "'");
      98             : 
      99             :     // Verify that any used symbols are defined.
     100          72 :     if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined())
     101           0 :       report_fatal_error("unable to evaluate offset to undefined symbol '" +
     102           0 :                          Target.getSymA()->getSymbol().getName() + "'");
     103          42 :     if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined())
     104           0 :       report_fatal_error("unable to evaluate offset to undefined symbol '" +
     105           0 :                          Target.getSymB()->getSymbol().getName() + "'");
     106             : 
     107          36 :     uint64_t Address = Target.getConstant();
     108          36 :     if (Target.getSymA())
     109          36 :       Address += getSymbolAddress(Target.getSymA()->getSymbol(), Layout);
     110          36 :     if (Target.getSymB())
     111           3 :       Address += getSymbolAddress(Target.getSymB()->getSymbol(), Layout);
     112             :     return Address;
     113             :   }
     114             : 
     115        2382 :   return getSectionAddress(S.getFragment()->getParent()) +
     116        2382 :          Layout.getSymbolOffset(S);
     117             : }
     118             : 
     119       10758 : uint64_t MachObjectWriter::getPaddingSize(const MCSection *Sec,
     120             :                                           const MCAsmLayout &Layout) const {
     121       10758 :   uint64_t EndAddr = getSectionAddress(Sec) + Layout.getSectionAddressSize(Sec);
     122       10758 :   unsigned Next = Sec->getLayoutOrder() + 1;
     123       21516 :   if (Next >= Layout.getSectionOrder().size())
     124             :     return 0;
     125             : 
     126        8991 :   const MCSection &NextSec = *Layout.getSectionOrder()[Next];
     127        8991 :   if (NextSec.isVirtualSection())
     128             :     return 0;
     129       17742 :   return OffsetToAlignment(EndAddr, NextSec.getAlignment());
     130             : }
     131             : 
     132         621 : void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
     133             :                                    unsigned NumLoadCommands,
     134             :                                    unsigned LoadCommandsSize,
     135             :                                    bool SubsectionsViaSymbols) {
     136             :   uint32_t Flags = 0;
     137             : 
     138         621 :   if (SubsectionsViaSymbols)
     139             :     Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
     140             : 
     141             :   // struct mach_header (28 bytes) or
     142             :   // struct mach_header_64 (32 bytes)
     143             : 
     144         621 :   uint64_t Start = getStream().tell();
     145             :   (void) Start;
     146             : 
     147        1242 :   write32(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
     148             : 
     149         621 :   write32(TargetObjectWriter->getCPUType());
     150         621 :   write32(TargetObjectWriter->getCPUSubtype());
     151             : 
     152         621 :   write32(Type);
     153         621 :   write32(NumLoadCommands);
     154         621 :   write32(LoadCommandsSize);
     155         621 :   write32(Flags);
     156         621 :   if (is64Bit())
     157         430 :     write32(0); // reserved
     158             : 
     159             :   assert(
     160             :       getStream().tell() - Start ==
     161             :       (is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header)));
     162         621 : }
     163             : 
     164             : /// writeSegmentLoadCommand - Write a segment load command.
     165             : ///
     166             : /// \param NumSections The number of sections in this segment.
     167             : /// \param SectionDataSize The total size of the sections.
     168         621 : void MachObjectWriter::writeSegmentLoadCommand(
     169             :     StringRef Name, unsigned NumSections, uint64_t VMAddr, uint64_t VMSize,
     170             :     uint64_t SectionDataStartOffset, uint64_t SectionDataSize, uint32_t MaxProt,
     171             :     uint32_t InitProt) {
     172             :   // struct segment_command (56 bytes) or
     173             :   // struct segment_command_64 (72 bytes)
     174             : 
     175         621 :   uint64_t Start = getStream().tell();
     176             :   (void) Start;
     177             : 
     178             :   unsigned SegmentLoadCommandSize =
     179             :     is64Bit() ? sizeof(MachO::segment_command_64):
     180         621 :     sizeof(MachO::segment_command);
     181         621 :   write32(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
     182         621 :   write32(SegmentLoadCommandSize +
     183             :           NumSections * (is64Bit() ? sizeof(MachO::section_64) :
     184             :                          sizeof(MachO::section)));
     185             : 
     186             :   assert(Name.size() <= 16);
     187             :   writeBytes(Name, 16);
     188         621 :   if (is64Bit()) {
     189         430 :     write64(VMAddr);                 // vmaddr
     190         430 :     write64(VMSize); // vmsize
     191         430 :     write64(SectionDataStartOffset); // file offset
     192         430 :     write64(SectionDataSize); // file size
     193             :   } else {
     194         191 :     write32(VMAddr);                 // vmaddr
     195         191 :     write32(VMSize); // vmsize
     196         191 :     write32(SectionDataStartOffset); // file offset
     197         191 :     write32(SectionDataSize); // file size
     198             :   }
     199             :   // maxprot
     200         621 :   write32(MaxProt);
     201             :   // initprot
     202         621 :   write32(InitProt);
     203         621 :   write32(NumSections);
     204         621 :   write32(0); // flags
     205             : 
     206             :   assert(getStream().tell() - Start == SegmentLoadCommandSize);
     207         621 : }
     208             : 
     209        3931 : void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
     210             :                                     const MCSection &Sec, uint64_t VMAddr,
     211             :                                     uint64_t FileOffset, unsigned Flags,
     212             :                                     uint64_t RelocationsStart,
     213             :                                     unsigned NumRelocations) {
     214        3931 :   uint64_t SectionSize = Layout.getSectionAddressSize(&Sec);
     215             :   const MCSectionMachO &Section = cast<MCSectionMachO>(Sec);
     216             : 
     217             :   // The offset is unused for virtual sections.
     218        3931 :   if (Section.isVirtualSection()) {
     219             :     assert(Layout.getSectionFileSize(&Sec) == 0 && "Invalid file size!");
     220             :     FileOffset = 0;
     221             :   }
     222             : 
     223             :   // struct section (68 bytes) or
     224             :   // struct section_64 (80 bytes)
     225             : 
     226        3931 :   uint64_t Start = getStream().tell();
     227             :   (void) Start;
     228             : 
     229             :   writeBytes(Section.getSectionName(), 16);
     230             :   writeBytes(Section.getSegmentName(), 16);
     231        3931 :   if (is64Bit()) {
     232        3237 :     write64(VMAddr);      // address
     233        3237 :     write64(SectionSize); // size
     234             :   } else {
     235         694 :     write32(VMAddr);      // address
     236         694 :     write32(SectionSize); // size
     237             :   }
     238        3931 :   write32(FileOffset);
     239             : 
     240             :   assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!");
     241        7862 :   write32(Log2_32(Section.getAlignment()));
     242        3931 :   write32(NumRelocations ? RelocationsStart : 0);
     243        3931 :   write32(NumRelocations);
     244        3931 :   write32(Flags);
     245        7862 :   write32(IndirectSymBase.lookup(&Sec)); // reserved1
     246        3931 :   write32(Section.getStubSize()); // reserved2
     247        3931 :   if (is64Bit())
     248        3237 :     write32(0); // reserved3
     249             : 
     250             :   assert(getStream().tell() - Start ==
     251             :          (is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));
     252        3931 : }
     253             : 
     254         515 : void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,
     255             :                                               uint32_t NumSymbols,
     256             :                                               uint32_t StringTableOffset,
     257             :                                               uint32_t StringTableSize) {
     258             :   // struct symtab_command (24 bytes)
     259             : 
     260         515 :   uint64_t Start = getStream().tell();
     261             :   (void) Start;
     262             : 
     263         515 :   write32(MachO::LC_SYMTAB);
     264         515 :   write32(sizeof(MachO::symtab_command));
     265         515 :   write32(SymbolOffset);
     266         515 :   write32(NumSymbols);
     267         515 :   write32(StringTableOffset);
     268         515 :   write32(StringTableSize);
     269             : 
     270             :   assert(getStream().tell() - Start == sizeof(MachO::symtab_command));
     271         515 : }
     272             : 
     273         468 : void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
     274             :                                                 uint32_t NumLocalSymbols,
     275             :                                                 uint32_t FirstExternalSymbol,
     276             :                                                 uint32_t NumExternalSymbols,
     277             :                                                 uint32_t FirstUndefinedSymbol,
     278             :                                                 uint32_t NumUndefinedSymbols,
     279             :                                                 uint32_t IndirectSymbolOffset,
     280             :                                                 uint32_t NumIndirectSymbols) {
     281             :   // struct dysymtab_command (80 bytes)
     282             : 
     283         468 :   uint64_t Start = getStream().tell();
     284             :   (void) Start;
     285             : 
     286         468 :   write32(MachO::LC_DYSYMTAB);
     287         468 :   write32(sizeof(MachO::dysymtab_command));
     288         468 :   write32(FirstLocalSymbol);
     289         468 :   write32(NumLocalSymbols);
     290         468 :   write32(FirstExternalSymbol);
     291         468 :   write32(NumExternalSymbols);
     292         468 :   write32(FirstUndefinedSymbol);
     293         468 :   write32(NumUndefinedSymbols);
     294         468 :   write32(0); // tocoff
     295         468 :   write32(0); // ntoc
     296         468 :   write32(0); // modtaboff
     297         468 :   write32(0); // nmodtab
     298         468 :   write32(0); // extrefsymoff
     299         468 :   write32(0); // nextrefsyms
     300         468 :   write32(IndirectSymbolOffset);
     301         468 :   write32(NumIndirectSymbols);
     302         468 :   write32(0); // extreloff
     303         468 :   write32(0); // nextrel
     304         468 :   write32(0); // locreloff
     305         468 :   write32(0); // nlocrel
     306             : 
     307             :   assert(getStream().tell() - Start == sizeof(MachO::dysymtab_command));
     308         468 : }
     309             : 
     310             : MachObjectWriter::MachSymbolData *
     311          24 : MachObjectWriter::findSymbolData(const MCSymbol &Sym) {
     312          69 :   for (auto *SymbolData :
     313          24 :        {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
     314         151 :     for (MachSymbolData &Entry : *SymbolData)
     315         127 :       if (Entry.Symbol == &Sym)
     316             :         return &Entry;
     317             : 
     318             :   return nullptr;
     319             : }
     320             : 
     321        5809 : const MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const {
     322             :   const MCSymbol *S = &Sym;
     323        5867 :   while (S->isVariable()) {
     324             :     const MCExpr *Value = S->getVariableValue();
     325             :     const auto *Ref = dyn_cast<MCSymbolRefExpr>(Value);
     326             :     if (!Ref)
     327             :       return *S;
     328          29 :     S = &Ref->getSymbol();
     329             :   }
     330             :   return *S;
     331             : }
     332             : 
     333        1619 : void MachObjectWriter::writeNlist(MachSymbolData &MSD,
     334             :                                   const MCAsmLayout &Layout) {
     335        1619 :   const MCSymbol *Symbol = MSD.Symbol;
     336             :   const MCSymbol &Data = *Symbol;
     337        1619 :   const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol);
     338        1619 :   uint8_t SectionIndex = MSD.SectionIndex;
     339             :   uint8_t Type = 0;
     340             :   uint64_t Address = 0;
     341             :   bool IsAlias = Symbol != AliasedSymbol;
     342             : 
     343             :   const MCSymbol &OrigSymbol = *Symbol;
     344             :   MachSymbolData *AliaseeInfo;
     345        1619 :   if (IsAlias) {
     346          24 :     AliaseeInfo = findSymbolData(*AliasedSymbol);
     347          24 :     if (AliaseeInfo)
     348          21 :       SectionIndex = AliaseeInfo->SectionIndex;
     349             :     Symbol = AliasedSymbol;
     350             :     // FIXME: Should this update Data as well?
     351             :   }
     352             : 
     353             :   // Set the N_TYPE bits. See <mach-o/nlist.h>.
     354             :   //
     355             :   // FIXME: Are the prebound or indirect fields possible here?
     356        1643 :   if (IsAlias && Symbol->isUndefined())
     357             :     Type = MachO::N_INDR;
     358        1614 :   else if (Symbol->isUndefined())
     359             :     Type = MachO::N_UNDF;
     360        1157 :   else if (Symbol->isAbsolute())
     361             :     Type = MachO::N_ABS;
     362             :   else
     363             :     Type = MachO::N_SECT;
     364             : 
     365             :   // FIXME: Set STAB bits.
     366             : 
     367        1619 :   if (Data.isPrivateExtern())
     368          21 :     Type |= MachO::N_PEXT;
     369             : 
     370             :   // Set external bit.
     371        2539 :   if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))
     372        1061 :     Type |= MachO::N_EXT;
     373             : 
     374             :   // Compute the symbol address.
     375        1643 :   if (IsAlias && Symbol->isUndefined())
     376           5 :     Address = AliaseeInfo->StringIndex;
     377        1614 :   else if (Symbol->isDefined())
     378        1157 :     Address = getSymbolAddress(OrigSymbol, Layout);
     379             :   else if (Symbol->isCommon()) {
     380             :     // Common symbols are encoded with the size in the address
     381             :     // field, and their alignment in the flags.
     382          52 :     Address = Symbol->getCommonSize();
     383             :   }
     384             : 
     385             :   // struct nlist (12 bytes)
     386             : 
     387        1619 :   write32(MSD.StringIndex);
     388        1619 :   write8(Type);
     389        1619 :   write8(SectionIndex);
     390             : 
     391             :   // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
     392             :   // value.
     393             :   bool EncodeAsAltEntry =
     394        1643 :     IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
     395        1619 :   write16(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
     396        1619 :   if (is64Bit())
     397         968 :     write64(Address);
     398             :   else
     399         651 :     write32(Address);
     400        1619 : }
     401             : 
     402          17 : void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
     403             :                                                 uint32_t DataOffset,
     404             :                                                 uint32_t DataSize) {
     405          17 :   uint64_t Start = getStream().tell();
     406             :   (void) Start;
     407             : 
     408          17 :   write32(Type);
     409          17 :   write32(sizeof(MachO::linkedit_data_command));
     410          17 :   write32(DataOffset);
     411          17 :   write32(DataSize);
     412             : 
     413             :   assert(getStream().tell() - Start == sizeof(MachO::linkedit_data_command));
     414          17 : }
     415             : 
     416             : static unsigned ComputeLinkerOptionsLoadCommandSize(
     417             :   const std::vector<std::string> &Options, bool is64Bit)
     418             : {
     419             :   unsigned Size = sizeof(MachO::linker_option_command);
     420          10 :   for (const std::string &Option : Options)
     421          14 :     Size += Option.size() + 1;
     422          15 :   return alignTo(Size, is64Bit ? 8 : 4);
     423             : }
     424             : 
     425           5 : void MachObjectWriter::writeLinkerOptionsLoadCommand(
     426             :   const std::vector<std::string> &Options)
     427             : {
     428             :   unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());
     429           5 :   uint64_t Start = getStream().tell();
     430             :   (void) Start;
     431             : 
     432           5 :   write32(MachO::LC_LINKER_OPTION);
     433           5 :   write32(Size);
     434          10 :   write32(Options.size());
     435             :   uint64_t BytesWritten = sizeof(MachO::linker_option_command);
     436           5 :   for (const std::string &Option : Options) {
     437             :     // Write each string, including the null byte.
     438          14 :     writeBytes(Option, Option.size() + 1);
     439           7 :     BytesWritten += Option.size() + 1;
     440             :   }
     441             : 
     442             :   // Pad to a multiple of the pointer size.
     443          15 :   writeBytes("", OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
     444             : 
     445             :   assert(getStream().tell() - Start == Size);
     446           5 : }
     447             : 
     448        3336 : void MachObjectWriter::recordRelocation(MCAssembler &Asm,
     449             :                                         const MCAsmLayout &Layout,
     450             :                                         const MCFragment *Fragment,
     451             :                                         const MCFixup &Fixup, MCValue Target,
     452             :                                         uint64_t &FixedValue) {
     453        3336 :   TargetObjectWriter->recordRelocation(this, Asm, Layout, Fragment, Fixup,
     454        3336 :                                        Target, FixedValue);
     455        3336 : }
     456             : 
     457         622 : void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) {
     458             :   // This is the point where 'as' creates actual symbols for indirect symbols
     459             :   // (in the following two passes). It would be easier for us to do this sooner
     460             :   // when we see the attribute, but that makes getting the order in the symbol
     461             :   // table much more complicated than it is worth.
     462             :   //
     463             :   // FIXME: Revisit this when the dust settles.
     464             : 
     465             :   // Report errors for use of .indirect_symbol not in a symbol pointer section
     466             :   // or stub section.
     467             :   for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
     468         663 :          ie = Asm.indirect_symbol_end(); it != ie; ++it) {
     469          41 :     const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
     470             : 
     471          54 :     if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
     472           7 :         Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
     473          46 :         Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
     474             :         Section.getType() != MachO::S_SYMBOL_STUBS) {
     475           0 :       MCSymbol &Symbol = *it->Symbol;
     476           0 :       report_fatal_error("indirect symbol '" + Symbol.getName() +
     477             :                          "' not in a symbol pointer or stub section");
     478             :     }
     479             :   }
     480             : 
     481             :   // Bind non-lazy symbol pointers first.
     482             :   unsigned IndirectIndex = 0;
     483          41 :   for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
     484         663 :          ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
     485          41 :     const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
     486             : 
     487          93 :     if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
     488             :         Section.getType() !=  MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
     489          11 :       continue;
     490             : 
     491             :     // Initialize the section indirect symbol base, if necessary.
     492          60 :     IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
     493             : 
     494          30 :     Asm.registerSymbol(*it->Symbol);
     495             :   }
     496             : 
     497             :   // Then lazy symbol pointers and symbol stubs.
     498             :   IndirectIndex = 0;
     499          41 :   for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
     500         663 :          ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
     501          41 :     const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
     502             : 
     503         112 :     if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
     504             :         Section.getType() != MachO::S_SYMBOL_STUBS)
     505          30 :       continue;
     506             : 
     507             :     // Initialize the section indirect symbol base, if necessary.
     508          22 :     IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
     509             : 
     510             :     // Set the symbol type to undefined lazy, but only on construction.
     511             :     //
     512             :     // FIXME: Do not hardcode.
     513             :     bool Created;
     514          11 :     Asm.registerSymbol(*it->Symbol, &Created);
     515          11 :     if (Created)
     516           4 :       cast<MCSymbolMachO>(it->Symbol)->setReferenceTypeUndefinedLazy(true);
     517             :   }
     518         622 : }
     519             : 
     520             : /// computeSymbolTable - Compute the symbol table data
     521         574 : void MachObjectWriter::computeSymbolTable(
     522             :     MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData,
     523             :     std::vector<MachSymbolData> &ExternalSymbolData,
     524             :     std::vector<MachSymbolData> &UndefinedSymbolData) {
     525             :   // Build section lookup table.
     526             :   DenseMap<const MCSection*, uint8_t> SectionIndexMap;
     527             :   unsigned Index = 1;
     528        3405 :   for (MCAssembler::iterator it = Asm.begin(),
     529        3979 :          ie = Asm.end(); it != ie; ++it, ++Index)
     530        6810 :     SectionIndexMap[&*it] = Index;
     531             :   assert(Index <= 256 && "Too many sections!");
     532             : 
     533             :   // Build the string table.
     534       16141 :   for (const MCSymbol &Symbol : Asm.symbols()) {
     535       15567 :     if (!Asm.isSymbolLinkerVisible(Symbol))
     536       13947 :       continue;
     537             : 
     538        3240 :     StringTable.add(Symbol.getName());
     539             :   }
     540         574 :   StringTable.finalize();
     541             : 
     542             :   // Build the symbol arrays but only for non-local symbols.
     543             :   //
     544             :   // The particular order that we collect and then sort the symbols is chosen to
     545             :   // match 'as'. Even though it doesn't matter for correctness, this is
     546             :   // important for letting us diff .o files.
     547       16141 :   for (const MCSymbol &Symbol : Asm.symbols()) {
     548             :     // Ignore non-linker visible symbols.
     549       15567 :     if (!Asm.isSymbolLinkerVisible(Symbol))
     550       28452 :       continue;
     551             : 
     552        2556 :     if (!Symbol.isExternal() && !Symbol.isUndefined())
     553         558 :       continue;
     554             : 
     555             :     MachSymbolData MSD;
     556        1062 :     MSD.Symbol = &Symbol;
     557        1062 :     MSD.StringIndex = StringTable.getOffset(Symbol.getName());
     558             : 
     559        1062 :     if (Symbol.isUndefined()) {
     560         462 :       MSD.SectionIndex = 0;
     561         462 :       UndefinedSymbolData.push_back(MSD);
     562         600 :     } else if (Symbol.isAbsolute()) {
     563           3 :       MSD.SectionIndex = 0;
     564           3 :       ExternalSymbolData.push_back(MSD);
     565             :     } else {
     566         597 :       MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
     567             :       assert(MSD.SectionIndex && "Invalid section index!");
     568         597 :       ExternalSymbolData.push_back(MSD);
     569             :     }
     570             :   }
     571             : 
     572             :   // Now add the data for local symbols.
     573       16141 :   for (const MCSymbol &Symbol : Asm.symbols()) {
     574             :     // Ignore non-linker visible symbols.
     575       15567 :     if (!Asm.isSymbolLinkerVisible(Symbol))
     576       28956 :       continue;
     577             : 
     578        3618 :     if (Symbol.isExternal() || Symbol.isUndefined())
     579        1062 :       continue;
     580             : 
     581             :     MachSymbolData MSD;
     582         558 :     MSD.Symbol = &Symbol;
     583         558 :     MSD.StringIndex = StringTable.getOffset(Symbol.getName());
     584             : 
     585         558 :     if (Symbol.isAbsolute()) {
     586           4 :       MSD.SectionIndex = 0;
     587           4 :       LocalSymbolData.push_back(MSD);
     588             :     } else {
     589         554 :       MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
     590             :       assert(MSD.SectionIndex && "Invalid section index!");
     591         554 :       LocalSymbolData.push_back(MSD);
     592             :     }
     593             :   }
     594             : 
     595             :   // External and undefined symbols are required to be in lexicographic order.
     596             :   std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
     597             :   std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
     598             : 
     599             :   // Set the symbol indices.
     600             :   Index = 0;
     601        3444 :   for (auto *SymbolData :
     602         574 :        {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
     603        3342 :     for (MachSymbolData &Entry : *SymbolData)
     604        1620 :       Entry.Symbol->setIndex(Index++);
     605             : 
     606        3979 :   for (const MCSection &Section : Asm) {
     607       13372 :     for (RelAndSymbol &Rel : Relocations[&Section]) {
     608        3157 :       if (!Rel.Sym)
     609        1291 :         continue;
     610             : 
     611             :       // Set the Index and the IsExtern bit.
     612        1866 :       unsigned Index = Rel.Sym->getIndex();
     613             :       assert(isInt<24>(Index));
     614        1866 :       if (IsLittleEndian)
     615        1865 :         Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);
     616             :       else
     617           1 :         Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
     618             :     }
     619             :   }
     620         574 : }
     621             : 
     622         622 : void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm,
     623             :                                                const MCAsmLayout &Layout) {
     624             :   uint64_t StartAddress = 0;
     625        8518 :   for (const MCSection *Sec : Layout.getSectionOrder()) {
     626        3948 :     StartAddress = alignTo(StartAddress, Sec->getAlignment());
     627        7896 :     SectionAddress[Sec] = StartAddress;
     628        3948 :     StartAddress += Layout.getSectionAddressSize(Sec);
     629             : 
     630             :     // Explicitly pad the section to match the alignment requirements of the
     631             :     // following one. This is for 'gas' compatibility, it shouldn't
     632             :     /// strictly be necessary.
     633        3948 :     StartAddress += getPaddingSize(Sec, Layout);
     634             :   }
     635         622 : }
     636             : 
     637         622 : void MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
     638             :                                                 const MCAsmLayout &Layout) {
     639         622 :   computeSectionAddresses(Asm, Layout);
     640             : 
     641             :   // Create symbol data for any indirect symbols.
     642         622 :   bindIndirectSymbols(Asm);
     643         622 : }
     644             : 
     645        8469 : bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
     646             :     const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B,
     647             :     bool InSet) const {
     648             :   // FIXME: We don't handle things like
     649             :   // foo = .
     650             :   // creating atoms.
     651       16936 :   if (A.isVariable() || B.isVariable())
     652             :     return false;
     653        8466 :   return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, A, B,
     654        8466 :                                                                 InSet);
     655             : }
     656             : 
     657        9546 : bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
     658             :     const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
     659             :     bool InSet, bool IsPCRel) const {
     660        9546 :   if (InSet)
     661             :     return true;
     662             : 
     663             :   // The effective address is
     664             :   //     addr(atom(A)) + offset(A)
     665             :   //   - addr(atom(B)) - offset(B)
     666             :   // and the offsets are not relocatable, so the fixup is fully resolved when
     667             :   //  addr(atom(A)) - addr(atom(B)) == 0.
     668        4178 :   const MCSymbol &SA = findAliasedSymbol(SymA);
     669             :   const MCSection &SecA = SA.getSection();
     670        4178 :   const MCSection &SecB = *FB.getParent();
     671             : 
     672        4178 :   if (IsPCRel) {
     673             :     // The simple (Darwin, except on x86_64) way of dealing with this was to
     674             :     // assume that any reference to a temporary symbol *must* be a temporary
     675             :     // symbol in the same atom, unless the sections differ. Therefore, any PCrel
     676             :     // relocation to a temporary symbol (in the same section) is fully
     677             :     // resolved. This also works in conjunction with absolutized .set, which
     678             :     // requires the compiler to use .set to absolutize the differences between
     679             :     // symbols which the compiler knows to be assembly time constants, so we
     680             :     // don't need to worry about considering symbol differences fully resolved.
     681             :     //
     682             :     // If the file isn't using sub-sections-via-symbols, we can make the
     683             :     // same assumptions about any symbol that we normally make about
     684             :     // assembler locals.
     685             : 
     686             :     bool hasReliableSymbolDifference = isX86_64();
     687        1080 :     if (!hasReliableSymbolDifference) {
     688        1365 :       if (!SA.isInSection() || &SecA != &SecB ||
     689         107 :           (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() &&
     690             :            Asm.getSubsectionsViaSymbols()))
     691             :         return false;
     692             :       return true;
     693             :     }
     694             :     // For Darwin x86_64, there is one special case when the reference IsPCRel.
     695             :     // If the fragment with the reference does not have a base symbol but meets
     696             :     // the simple way of dealing with this, in that it is a temporary symbol in
     697             :     // the same atom then it is assumed to be fully resolved.  This is needed so
     698             :     // a relocation entry is not created and so the static linker does not
     699             :     // mess up the reference later.
     700         435 :     else if(!FB.getAtom() &&
     701         421 :             SA.isTemporary() && SA.isInSection() && &SecA == &SecB){
     702             :       return true;
     703             :     }
     704             :   }
     705             : 
     706             :   // If they are not in the same section, we can't compute the diff.
     707        3487 :   if (&SecA != &SecB)
     708             :     return false;
     709             : 
     710        3260 :   const MCFragment *FA = SA.getFragment();
     711             : 
     712             :   // Bail if the symbol has no fragment.
     713        3260 :   if (!FA)
     714             :     return false;
     715             : 
     716             :   // If the atoms are the same, they are guaranteed to have the same address.
     717        3260 :   if (FA->getAtom() == FB.getAtom())
     718             :     return true;
     719             : 
     720             :   // Otherwise, we can't prove this is fully resolved.
     721         185 :   return false;
     722             : }
     723             : 
     724             : static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
     725         321 :   switch (Type) {
     726             :   case MCVM_OSXVersionMin:     return MachO::LC_VERSION_MIN_MACOSX;
     727          19 :   case MCVM_IOSVersionMin:     return MachO::LC_VERSION_MIN_IPHONEOS;
     728           2 :   case MCVM_TvOSVersionMin:    return MachO::LC_VERSION_MIN_TVOS;
     729           3 :   case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS;
     730             :   }
     731           0 :   llvm_unreachable("Invalid mc version min type");
     732             : }
     733             : 
     734         574 : void MachObjectWriter::writeObject(MCAssembler &Asm,
     735             :                                    const MCAsmLayout &Layout) {
     736             :   // Compute symbol table information and bind symbol indices.
     737         574 :   computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
     738             :                      UndefinedSymbolData);
     739             : 
     740         574 :   unsigned NumSections = Asm.size();
     741             :   const MCAssembler::VersionInfoType &VersionInfo =
     742         574 :     Layout.getAssembler().getVersionInfo();
     743             : 
     744             :   // The section data starts after the header, the segment load command (and
     745             :   // section headers) and the symbol table.
     746             :   unsigned NumLoadCommands = 1;
     747        1148 :   uint64_t LoadCommandsSize = is64Bit() ?
     748         386 :     sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):
     749         188 :     sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
     750             : 
     751             :   // Add the deployment target version info load command size, if used.
     752         574 :   if (VersionInfo.Major != 0) {
     753             :     ++NumLoadCommands;
     754         322 :     if (VersionInfo.EmitBuildVersion)
     755           1 :       LoadCommandsSize += sizeof(MachO::build_version_command);
     756             :     else
     757         321 :       LoadCommandsSize += sizeof(MachO::version_min_command);
     758             :   }
     759             : 
     760             :   // Add the data-in-code load command size, if used.
     761        1148 :   unsigned NumDataRegions = Asm.getDataRegions().size();
     762         574 :   if (NumDataRegions) {
     763          16 :     ++NumLoadCommands;
     764          16 :     LoadCommandsSize += sizeof(MachO::linkedit_data_command);
     765             :   }
     766             : 
     767             :   // Add the loh load command size, if used.
     768         574 :   uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout);
     769         574 :   uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4);
     770         574 :   if (LOHSize) {
     771           1 :     ++NumLoadCommands;
     772           1 :     LoadCommandsSize += sizeof(MachO::linkedit_data_command);
     773             :   }
     774             : 
     775             :   // Add the symbol table load command sizes, if used.
     776        2296 :   unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
     777        1148 :     UndefinedSymbolData.size();
     778         574 :   if (NumSymbols) {
     779         468 :     NumLoadCommands += 2;
     780         468 :     LoadCommandsSize += (sizeof(MachO::symtab_command) +
     781             :                          sizeof(MachO::dysymtab_command));
     782             :   }
     783             : 
     784             :   // Add the linker option load commands sizes.
     785         579 :   for (const auto &Option : Asm.getLinkerOptions()) {
     786           5 :     ++NumLoadCommands;
     787           5 :     LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(Option, is64Bit());
     788             :   }
     789             : 
     790             :   // Compute the total size of the section data, as well as its file size and vm
     791             :   // size.
     792         574 :   uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) :
     793         574 :                                sizeof(MachO::mach_header)) + LoadCommandsSize;
     794         574 :   uint64_t SectionDataSize = 0;
     795         574 :   uint64_t SectionDataFileSize = 0;
     796         574 :   uint64_t VMSize = 0;
     797        3979 :   for (const MCSection &Sec : Asm) {
     798             :     uint64_t Address = getSectionAddress(&Sec);
     799        3405 :     uint64_t Size = Layout.getSectionAddressSize(&Sec);
     800        3405 :     uint64_t FileSize = Layout.getSectionFileSize(&Sec);
     801        3405 :     FileSize += getPaddingSize(&Sec, Layout);
     802             : 
     803        6810 :     VMSize = std::max(VMSize, Address + Size);
     804             : 
     805        3405 :     if (Sec.isVirtualSection())
     806          40 :       continue;
     807             : 
     808        6730 :     SectionDataSize = std::max(SectionDataSize, Address + Size);
     809        6730 :     SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
     810             :   }
     811             : 
     812             :   // The section data is padded to 4 bytes.
     813             :   //
     814             :   // FIXME: Is this machine dependent?
     815        1148 :   unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
     816         574 :   SectionDataFileSize += SectionDataPadding;
     817             : 
     818             :   // Write the prolog, starting with the header and load command...
     819         574 :   writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize,
     820             :               Asm.getSubsectionsViaSymbols());
     821             :   uint32_t Prot =
     822             :       MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
     823        1148 :   writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart,
     824             :                           SectionDataSize, Prot, Prot);
     825             : 
     826             :   // ... and then the section headers.
     827         574 :   uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
     828        3979 :   for (const MCSection &Section : Asm) {
     829             :     const auto &Sec = cast<MCSectionMachO>(Section);
     830        6810 :     std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
     831        6810 :     unsigned NumRelocs = Relocs.size();
     832        3405 :     uint64_t SectionStart = SectionDataStart + getSectionAddress(&Sec);
     833        3405 :     unsigned Flags = Sec.getTypeAndAttributes();
     834        3405 :     if (Sec.hasInstructions())
     835         394 :       Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS;
     836        3405 :     writeSection(Layout, Sec, getSectionAddress(&Sec), SectionStart, Flags,
     837             :                  RelocTableEnd, NumRelocs);
     838        3405 :     RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);
     839             :   }
     840             : 
     841             :   // Write out the deployment target information, if it's available.
     842         574 :   if (VersionInfo.Major != 0) {
     843             :     assert(VersionInfo.Update < 256 && "unencodable update target version");
     844             :     assert(VersionInfo.Minor < 256 && "unencodable minor target version");
     845             :     assert(VersionInfo.Major < 65536 && "unencodable major target version");
     846         644 :     uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) |
     847         322 :       (VersionInfo.Major << 16);
     848         322 :     if (VersionInfo.EmitBuildVersion) {
     849             :       // FIXME: Currently empty tools. Add clang version in the future.
     850           1 :       write32(MachO::LC_BUILD_VERSION);
     851           1 :       write32(sizeof(MachO::build_version_command));
     852           1 :       write32(VersionInfo.TypeOrPlatform.Platform);
     853           1 :       write32(EncodedVersion);
     854           1 :       write32(0);         // SDK version.
     855           1 :       write32(0);         // Empty tools list.
     856             :     } else {
     857             :       MachO::LoadCommandType LCType
     858         321 :         = getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
     859         321 :       write32(LCType);
     860         321 :       write32(sizeof(MachO::version_min_command));
     861         321 :       write32(EncodedVersion);
     862         321 :       write32(0);         // reserved.
     863             :     }
     864             :   }
     865             : 
     866             :   // Write the data-in-code load command, if used.
     867         574 :   uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
     868         574 :   if (NumDataRegions) {
     869             :     uint64_t DataRegionsOffset = RelocTableEnd;
     870             :     uint64_t DataRegionsSize = NumDataRegions * 8;
     871          16 :     writeLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset,
     872             :                              DataRegionsSize);
     873             :   }
     874             : 
     875             :   // Write the loh load command, if used.
     876         574 :   uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize;
     877         574 :   if (LOHSize)
     878           1 :     writeLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT,
     879             :                              DataInCodeTableEnd, LOHSize);
     880             : 
     881             :   // Write the symbol table load command, if used.
     882         574 :   if (NumSymbols) {
     883             :     unsigned FirstLocalSymbol = 0;
     884         936 :     unsigned NumLocalSymbols = LocalSymbolData.size();
     885             :     unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
     886         936 :     unsigned NumExternalSymbols = ExternalSymbolData.size();
     887         468 :     unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
     888         936 :     unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
     889         468 :     unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
     890         468 :     unsigned NumSymTabSymbols =
     891             :       NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
     892         468 :     uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
     893             :     uint64_t IndirectSymbolOffset = 0;
     894             : 
     895             :     // If used, the indirect symbols are written after the section data.
     896         468 :     if (NumIndirectSymbols)
     897             :       IndirectSymbolOffset = LOHTableEnd;
     898             : 
     899             :     // The symbol table is written after the indirect symbol data.
     900         468 :     uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize;
     901             : 
     902             :     // The string table is written after symbol table.
     903             :     uint64_t StringTableOffset =
     904         936 :       SymbolTableOffset + NumSymTabSymbols * (is64Bit() ?
     905             :                                               sizeof(MachO::nlist_64) :
     906         468 :                                               sizeof(MachO::nlist));
     907         468 :     writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
     908         468 :                            StringTableOffset, StringTable.getSize());
     909             : 
     910         468 :     writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
     911             :                              FirstExternalSymbol, NumExternalSymbols,
     912             :                              FirstUndefinedSymbol, NumUndefinedSymbols,
     913             :                              IndirectSymbolOffset, NumIndirectSymbols);
     914             :   }
     915             : 
     916             :   // Write the linker options load commands.
     917         579 :   for (const auto &Option : Asm.getLinkerOptions())
     918           5 :     writeLinkerOptionsLoadCommand(Option);
     919             : 
     920             :   // Write the actual section data.
     921        3979 :   for (const MCSection &Sec : Asm) {
     922        3405 :     Asm.writeSectionData(&Sec, Layout);
     923             : 
     924        3405 :     uint64_t Pad = getPaddingSize(&Sec, Layout);
     925        3405 :     WriteZeros(Pad);
     926             :   }
     927             : 
     928             :   // Write the extra padding.
     929         574 :   WriteZeros(SectionDataPadding);
     930             : 
     931             :   // Write the relocation entries.
     932        3979 :   for (const MCSection &Sec : Asm) {
     933             :     // Write the section relocation entries, in reverse order to match 'as'
     934             :     // (approximately, the exact algorithm is more complicated than this).
     935        6810 :     std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
     936        6562 :     for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) {
     937        3157 :       write32(Rel.MRE.r_word0);
     938        3157 :       write32(Rel.MRE.r_word1);
     939             :     }
     940             :   }
     941             : 
     942             :   // Write out the data-in-code region payload, if there is one.
     943             :   for (MCAssembler::const_data_region_iterator
     944             :          it = Asm.data_region_begin(), ie = Asm.data_region_end();
     945         621 :          it != ie; ++it) {
     946             :     const DataRegionData *Data = &(*it);
     947          48 :     uint64_t Start = getSymbolAddress(*Data->Start, Layout);
     948             :     uint64_t End;
     949          48 :     if (Data->End) 
     950          47 :       End = getSymbolAddress(*Data->End, Layout);
     951             :     else
     952           1 :       report_fatal_error("Data region not terminated");
     953             : 
     954             : 
     955             :     DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
     956             :                  << "  start: " << Start << "(" << Data->Start->getName() << ")"
     957             :                  << "  end: " << End << "(" << Data->End->getName() << ")"
     958             :                  << "  size: " << End - Start
     959             :                  << "\n");
     960          47 :     write32(Start);
     961          47 :     write16(End - Start);
     962          47 :     write16(Data->Kind);
     963             :   }
     964             : 
     965             :   // Write out the loh commands, if there is one.
     966         573 :   if (LOHSize) {
     967             : #ifndef NDEBUG
     968             :     unsigned Start = getStream().tell();
     969             : #endif
     970             :     Asm.getLOHContainer().emit(*this, Layout);
     971             :     // Pad to a multiple of the pointer size.
     972           4 :     writeBytes("", OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
     973             :     assert(getStream().tell() - Start == LOHSize);
     974             :   }
     975             : 
     976             :   // Write the symbol table data, if used.
     977         573 :   if (NumSymbols) {
     978             :     // Write the indirect symbol entries.
     979             :     for (MCAssembler::const_indirect_symbol_iterator
     980             :            it = Asm.indirect_symbol_begin(),
     981         508 :            ie = Asm.indirect_symbol_end(); it != ie; ++it) {
     982             :       // Indirect symbols in the non-lazy symbol pointer section have some
     983             :       // special handling.
     984             :       const MCSectionMachO &Section =
     985          41 :           static_cast<const MCSectionMachO &>(*it->Section);
     986          82 :       if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) {
     987             :         // If this symbol is defined and internal, mark it as such.
     988          60 :         if (it->Symbol->isDefined() && !it->Symbol->isExternal()) {
     989             :           uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
     990           3 :           if (it->Symbol->isAbsolute())
     991             :             Flags |= MachO::INDIRECT_SYMBOL_ABS;
     992           3 :           write32(Flags);
     993           3 :           continue;
     994             :         }
     995             :       }
     996             : 
     997          38 :       write32(it->Symbol->getIndex());
     998             :     }
     999             : 
    1000             :     // FIXME: Check that offsets match computed ones.
    1001             : 
    1002             :     // Write the symbol table entries.
    1003        2802 :     for (auto *SymbolData :
    1004         467 :          {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
    1005        3020 :       for (MachSymbolData &Entry : *SymbolData)
    1006        1619 :         writeNlist(Entry, Layout);
    1007             : 
    1008             :     // Write the string table.
    1009         467 :     StringTable.write(getStream());
    1010             :   }
    1011         573 : }
    1012             : 
    1013             : std::unique_ptr<MCObjectWriter>
    1014         625 : llvm::createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
    1015             :                              raw_pwrite_stream &OS, bool IsLittleEndian) {
    1016        1250 :   return llvm::make_unique<MachObjectWriter>(std::move(MOTW), OS,
    1017         625 :                                              IsLittleEndian);
    1018             : }

Generated by: LCOV version 1.13