brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.5 KiB · b42155d Raw
1122 lines · cpp
1//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/DenseMap.h"10#include "llvm/ADT/Twine.h"11#include "llvm/BinaryFormat/MachO.h"12#include "llvm/MC/MCAsmBackend.h"13#include "llvm/MC/MCAsmInfoDarwin.h"14#include "llvm/MC/MCAssembler.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCDirectives.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCMachObjectWriter.h"19#include "llvm/MC/MCObjectFileInfo.h"20#include "llvm/MC/MCObjectWriter.h"21#include "llvm/MC/MCSection.h"22#include "llvm/MC/MCSectionMachO.h"23#include "llvm/MC/MCSymbol.h"24#include "llvm/MC/MCSymbolMachO.h"25#include "llvm/MC/MCValue.h"26#include "llvm/Support/Alignment.h"27#include "llvm/Support/Casting.h"28#include "llvm/Support/Debug.h"29#include "llvm/Support/ErrorHandling.h"30#include "llvm/Support/MathExtras.h"31#include "llvm/Support/SMLoc.h"32#include "llvm/Support/raw_ostream.h"33#include <algorithm>34#include <cassert>35#include <cstdint>36#include <string>37#include <vector>38 39using namespace llvm;40 41#define DEBUG_TYPE "mc"42 43void MachObjectWriter::reset() {44  Relocations.clear();45  IndirectSymBase.clear();46  IndirectSymbols.clear();47  DataRegions.clear();48  SectionAddress.clear();49  SectionOrder.clear();50  StringTable.clear();51  LocalSymbolData.clear();52  ExternalSymbolData.clear();53  UndefinedSymbolData.clear();54  LOHContainer.reset();55  VersionInfo.Major = 0;56  VersionInfo.SDKVersion = VersionTuple();57  TargetVariantVersionInfo.Major = 0;58  TargetVariantVersionInfo.SDKVersion = VersionTuple();59  LinkerOptions.clear();60  MCObjectWriter::reset();61}62 63void MachObjectWriter::setAssembler(MCAssembler *Asm) {64  MCObjectWriter::setAssembler(Asm);65  TargetObjectWriter->setAssembler(Asm);66}67 68bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) {69  // Undefined symbols are always extern.70  if (S.isUndefined())71    return true;72 73  // References to weak definitions require external relocation entries; the74  // definition may not always be the one in the same object file.75  if (static_cast<const MCSymbolMachO &>(S).isWeakDefinition())76    return true;77 78  // Otherwise, we can use an internal relocation.79  return false;80}81 82bool MachObjectWriter::83MachSymbolData::operator<(const MachSymbolData &RHS) const {84  return Symbol->getName() < RHS.Symbol->getName();85}86 87uint64_t88MachObjectWriter::getFragmentAddress(const MCAssembler &Asm,89                                     const MCFragment *Fragment) const {90  return getSectionAddress(Fragment->getParent()) +91         Asm.getFragmentOffset(*Fragment);92}93 94uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S) const {95  // If this is a variable, then recursively evaluate now.96  if (S.isVariable()) {97    if (const MCConstantExpr *C =98          dyn_cast<const MCConstantExpr>(S.getVariableValue()))99      return C->getValue();100 101    MCValue Target;102    if (!S.getVariableValue()->evaluateAsRelocatable(Target, Asm))103      report_fatal_error("unable to evaluate offset for variable '" +104                         S.getName() + "'");105 106    // Verify that any used symbols are defined.107    if (Target.getAddSym() && Target.getAddSym()->isUndefined())108      report_fatal_error("unable to evaluate offset to undefined symbol '" +109                         Target.getAddSym()->getName() + "'");110    if (Target.getSubSym() && Target.getSubSym()->isUndefined())111      report_fatal_error("unable to evaluate offset to undefined symbol '" +112                         Target.getSubSym()->getName() + "'");113 114    uint64_t Address = Target.getConstant();115    if (Target.getAddSym())116      Address += getSymbolAddress(*Target.getAddSym());117    if (Target.getSubSym())118      Address -= getSymbolAddress(*Target.getSubSym());119    return Address;120  }121 122  return getSectionAddress(S.getFragment()->getParent()) +123         Asm->getSymbolOffset(S);124}125 126uint64_t MachObjectWriter::getPaddingSize(const MCAssembler &Asm,127                                          const MCSection *Sec) const {128  uint64_t EndAddr = getSectionAddress(Sec) + Asm.getSectionAddressSize(*Sec);129  unsigned Next =130      static_cast<const MCSectionMachO *>(Sec)->getLayoutOrder() + 1;131  if (Next >= SectionOrder.size())132    return 0;133 134  const MCSection &NextSec = *SectionOrder[Next];135  if (NextSec.isBssSection())136    return 0;137  return offsetToAlignment(EndAddr, NextSec.getAlign());138}139 140static bool isSymbolLinkerVisible(const MCSymbol &Symbol) {141  // Non-temporary labels should always be visible to the linker.142  if (!Symbol.isTemporary())143    return true;144 145  if (Symbol.isUsedInReloc())146    return true;147 148  return false;149}150 151const MCSymbol *MachObjectWriter::getAtom(const MCSymbol &S) const {152  // Linker visible symbols define atoms.153  if (isSymbolLinkerVisible(S))154    return &S;155 156  // Absolute and undefined symbols have no defining atom.157  if (!S.isInSection())158    return nullptr;159 160  // Non-linker visible symbols in sections which can't be atomized have no161  // defining atom.162  if (!MCAsmInfoDarwin::isSectionAtomizableBySymbols(163          *S.getFragment()->getParent()))164    return nullptr;165 166  // Otherwise, return the atom for the containing fragment.167  return S.getFragment()->getAtom();168}169 170void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,171                                   unsigned NumLoadCommands,172                                   unsigned LoadCommandsSize,173                                   bool SubsectionsViaSymbols) {174  uint32_t Flags = 0;175 176  if (SubsectionsViaSymbols)177    Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS;178 179  // struct mach_header (28 bytes) or180  // struct mach_header_64 (32 bytes)181 182  uint64_t Start = W.OS.tell();183  (void) Start;184 185  W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);186 187  W.write<uint32_t>(TargetObjectWriter->getCPUType());188 189  uint32_t Cpusubtype = TargetObjectWriter->getCPUSubtype();190 191  // Promote arm64e subtypes to always be ptrauth-ABI-versioned, at version 0.192  // We never need to emit unversioned binaries.193  // And we don't support arbitrary ABI versions (or the kernel flag) yet.194  if (TargetObjectWriter->getCPUType() == MachO::CPU_TYPE_ARM64 &&195      Cpusubtype == MachO::CPU_SUBTYPE_ARM64E)196    Cpusubtype = MachO::CPU_SUBTYPE_ARM64E_WITH_PTRAUTH_VERSION(197        /*PtrAuthABIVersion=*/0, /*PtrAuthKernelABIVersion=*/false);198 199  W.write<uint32_t>(Cpusubtype);200 201  W.write<uint32_t>(Type);202  W.write<uint32_t>(NumLoadCommands);203  W.write<uint32_t>(LoadCommandsSize);204  W.write<uint32_t>(Flags);205  if (is64Bit())206    W.write<uint32_t>(0); // reserved207 208  assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64)209                                           : sizeof(MachO::mach_header)));210}211 212void MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) {213  assert(Size >= Str.size());214  W.OS << Str;215  W.OS.write_zeros(Size - Str.size());216}217 218/// writeSegmentLoadCommand - Write a segment load command.219///220/// \param NumSections The number of sections in this segment.221/// \param SectionDataSize The total size of the sections.222void MachObjectWriter::writeSegmentLoadCommand(223    StringRef Name, unsigned NumSections, uint64_t VMAddr, uint64_t VMSize,224    uint64_t SectionDataStartOffset, uint64_t SectionDataSize, uint32_t MaxProt,225    uint32_t InitProt) {226  // struct segment_command (56 bytes) or227  // struct segment_command_64 (72 bytes)228 229  uint64_t Start = W.OS.tell();230  (void) Start;231 232  unsigned SegmentLoadCommandSize =233    is64Bit() ? sizeof(MachO::segment_command_64):234    sizeof(MachO::segment_command);235  W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);236  W.write<uint32_t>(SegmentLoadCommandSize +237          NumSections * (is64Bit() ? sizeof(MachO::section_64) :238                         sizeof(MachO::section)));239 240  writeWithPadding(Name, 16);241  if (is64Bit()) {242    W.write<uint64_t>(VMAddr);                 // vmaddr243    W.write<uint64_t>(VMSize); // vmsize244    W.write<uint64_t>(SectionDataStartOffset); // file offset245    W.write<uint64_t>(SectionDataSize); // file size246  } else {247    W.write<uint32_t>(VMAddr);                 // vmaddr248    W.write<uint32_t>(VMSize); // vmsize249    W.write<uint32_t>(SectionDataStartOffset); // file offset250    W.write<uint32_t>(SectionDataSize); // file size251  }252  // maxprot253  W.write<uint32_t>(MaxProt);254  // initprot255  W.write<uint32_t>(InitProt);256  W.write<uint32_t>(NumSections);257  W.write<uint32_t>(0); // flags258 259  assert(W.OS.tell() - Start == SegmentLoadCommandSize);260}261 262void MachObjectWriter::writeSection(const MCAssembler &Asm,263                                    const MCSectionMachO &Sec, uint64_t VMAddr,264                                    uint64_t FileOffset, unsigned Flags,265                                    uint64_t RelocationsStart,266                                    unsigned NumRelocations) {267  // The offset is unused for virtual sections.268  if (Sec.isBssSection()) {269    assert(Asm.getSectionFileSize(Sec) == 0 && "Invalid file size!");270    FileOffset = 0;271  }272 273  // struct section (68 bytes) or274  // struct section_64 (80 bytes)275 276  uint64_t SectionSize = Asm.getSectionAddressSize(Sec);277  uint64_t Start = W.OS.tell();278  (void) Start;279  writeWithPadding(Sec.getName(), 16);280  writeWithPadding(Sec.getSegmentName(), 16);281  if (is64Bit()) {282    W.write<uint64_t>(VMAddr);      // address283    W.write<uint64_t>(SectionSize); // size284  } else {285    W.write<uint32_t>(VMAddr);      // address286    W.write<uint32_t>(SectionSize); // size287  }288  assert(isUInt<32>(FileOffset) && "Cannot encode offset of section");289  W.write<uint32_t>(FileOffset);290 291  W.write<uint32_t>(Log2(Sec.getAlign()));292  assert((!NumRelocations || isUInt<32>(RelocationsStart)) &&293         "Cannot encode offset of relocations");294  W.write<uint32_t>(NumRelocations ? RelocationsStart : 0);295  W.write<uint32_t>(NumRelocations);296  W.write<uint32_t>(Flags);297  W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1298  W.write<uint32_t>(Sec.getStubSize());            // reserved2299  if (is64Bit())300    W.write<uint32_t>(0); // reserved3301 302  assert(W.OS.tell() - Start ==303         (is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));304}305 306void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,307                                              uint32_t NumSymbols,308                                              uint32_t StringTableOffset,309                                              uint32_t StringTableSize) {310  // struct symtab_command (24 bytes)311 312  uint64_t Start = W.OS.tell();313  (void) Start;314 315  W.write<uint32_t>(MachO::LC_SYMTAB);316  W.write<uint32_t>(sizeof(MachO::symtab_command));317  W.write<uint32_t>(SymbolOffset);318  W.write<uint32_t>(NumSymbols);319  W.write<uint32_t>(StringTableOffset);320  W.write<uint32_t>(StringTableSize);321 322  assert(W.OS.tell() - Start == sizeof(MachO::symtab_command));323}324 325void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,326                                                uint32_t NumLocalSymbols,327                                                uint32_t FirstExternalSymbol,328                                                uint32_t NumExternalSymbols,329                                                uint32_t FirstUndefinedSymbol,330                                                uint32_t NumUndefinedSymbols,331                                                uint32_t IndirectSymbolOffset,332                                                uint32_t NumIndirectSymbols) {333  // struct dysymtab_command (80 bytes)334 335  uint64_t Start = W.OS.tell();336  (void) Start;337 338  W.write<uint32_t>(MachO::LC_DYSYMTAB);339  W.write<uint32_t>(sizeof(MachO::dysymtab_command));340  W.write<uint32_t>(FirstLocalSymbol);341  W.write<uint32_t>(NumLocalSymbols);342  W.write<uint32_t>(FirstExternalSymbol);343  W.write<uint32_t>(NumExternalSymbols);344  W.write<uint32_t>(FirstUndefinedSymbol);345  W.write<uint32_t>(NumUndefinedSymbols);346  W.write<uint32_t>(0); // tocoff347  W.write<uint32_t>(0); // ntoc348  W.write<uint32_t>(0); // modtaboff349  W.write<uint32_t>(0); // nmodtab350  W.write<uint32_t>(0); // extrefsymoff351  W.write<uint32_t>(0); // nextrefsyms352  W.write<uint32_t>(IndirectSymbolOffset);353  W.write<uint32_t>(NumIndirectSymbols);354  W.write<uint32_t>(0); // extreloff355  W.write<uint32_t>(0); // nextrel356  W.write<uint32_t>(0); // locreloff357  W.write<uint32_t>(0); // nlocrel358 359  assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command));360}361 362MachObjectWriter::MachSymbolData *363MachObjectWriter::findSymbolData(const MCSymbol &Sym) {364  for (auto *SymbolData :365       {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})366    for (MachSymbolData &Entry : *SymbolData)367      if (Entry.Symbol == &Sym)368        return &Entry;369 370  return nullptr;371}372 373const MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const {374  const MCSymbol *S = &Sym;375  while (S->isVariable()) {376    const MCExpr *Value = S->getVariableValue();377    const auto *Ref = dyn_cast<MCSymbolRefExpr>(Value);378    if (!Ref)379      return *S;380    S = &Ref->getSymbol();381  }382  return *S;383}384 385void MachObjectWriter::writeNlist(MachSymbolData &MSD, const MCAssembler &Asm) {386  auto *Symbol = MSD.Symbol;387  const auto &Data = static_cast<const MCSymbolMachO &>(*Symbol);388  auto *AliasedSymbol =389      static_cast<const MCSymbolMachO *>(&findAliasedSymbol(*Symbol));390  uint8_t SectionIndex = MSD.SectionIndex;391  uint8_t Type = 0;392  uint64_t Address = 0;393  bool IsAlias = Symbol != AliasedSymbol;394 395  const MCSymbolMachO &OrigSymbol = *Symbol;396  MachSymbolData *AliaseeInfo;397  if (IsAlias) {398    AliaseeInfo = findSymbolData(*AliasedSymbol);399    if (AliaseeInfo)400      SectionIndex = AliaseeInfo->SectionIndex;401    Symbol = AliasedSymbol;402    // FIXME: Should this update Data as well?403  }404 405  // Set the N_TYPE bits. See <mach-o/nlist.h>.406  //407  // FIXME: Are the prebound or indirect fields possible here?408  if (IsAlias && Symbol->isUndefined())409    Type = MachO::N_INDR;410  else if (Symbol->isUndefined())411    Type = MachO::N_UNDF;412  else if (Symbol->isAbsolute())413    Type = MachO::N_ABS;414  else415    Type = MachO::N_SECT;416 417  // FIXME: Set STAB bits.418 419  if (Data.isPrivateExtern())420    Type |= MachO::N_PEXT;421 422  // Set external bit.423  if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))424    Type |= MachO::N_EXT;425 426  // Compute the symbol address.427  if (IsAlias && Symbol->isUndefined())428    Address = AliaseeInfo->StringIndex;429  else if (Symbol->isDefined())430    Address = getSymbolAddress(OrigSymbol);431  else if (Symbol->isCommon()) {432    // Common symbols are encoded with the size in the address433    // field, and their alignment in the flags.434    Address = Symbol->getCommonSize();435  }436 437  // struct nlist (12 bytes)438 439  W.write<uint32_t>(MSD.StringIndex);440  W.OS << char(Type);441  W.OS << char(SectionIndex);442 443  // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'444  // value.445  bool EncodeAsAltEntry = IsAlias && OrigSymbol.isAltEntry();446  W.write<uint16_t>(Symbol->getEncodedFlags(EncodeAsAltEntry));447  if (is64Bit())448    W.write<uint64_t>(Address);449  else450    W.write<uint32_t>(Address);451}452 453void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,454                                                uint32_t DataOffset,455                                                uint32_t DataSize) {456  uint64_t Start = W.OS.tell();457  (void) Start;458 459  W.write<uint32_t>(Type);460  W.write<uint32_t>(sizeof(MachO::linkedit_data_command));461  W.write<uint32_t>(DataOffset);462  W.write<uint32_t>(DataSize);463 464  assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command));465}466 467static unsigned ComputeLinkerOptionsLoadCommandSize(468  const std::vector<std::string> &Options, bool is64Bit)469{470  unsigned Size = sizeof(MachO::linker_option_command);471  for (const std::string &Option : Options)472    Size += Option.size() + 1;473  return alignTo(Size, is64Bit ? 8 : 4);474}475 476void MachObjectWriter::writeLinkerOptionsLoadCommand(477  const std::vector<std::string> &Options)478{479  unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());480  uint64_t Start = W.OS.tell();481  (void) Start;482 483  W.write<uint32_t>(MachO::LC_LINKER_OPTION);484  W.write<uint32_t>(Size);485  W.write<uint32_t>(Options.size());486  uint64_t BytesWritten = sizeof(MachO::linker_option_command);487  for (const std::string &Option : Options) {488    // Write each string, including the null byte.489    W.OS << Option << '\0';490    BytesWritten += Option.size() + 1;491  }492 493  // Pad to a multiple of the pointer size.494  W.OS.write_zeros(495      offsetToAlignment(BytesWritten, is64Bit() ? Align(8) : Align(4)));496 497  assert(W.OS.tell() - Start == Size);498}499 500static bool isFixupTargetValid(const MCValue &Target) {501  // Target is (LHS - RHS + cst).502  // We don't support the form where LHS is null: -RHS + cst503  if (!Target.getAddSym() && Target.getSubSym())504    return false;505  return true;506}507 508void MachObjectWriter::recordRelocation(const MCFragment &F,509                                        const MCFixup &Fixup, MCValue Target,510                                        uint64_t &FixedValue) {511  if (!isFixupTargetValid(Target)) {512    getContext().reportError(Fixup.getLoc(),513                             "unsupported relocation expression");514    return;515  }516 517  TargetObjectWriter->recordRelocation(this, *Asm, &F, Fixup, Target,518                                       FixedValue);519}520 521void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) {522  // This is the point where 'as' creates actual symbols for indirect symbols523  // (in the following two passes). It would be easier for us to do this sooner524  // when we see the attribute, but that makes getting the order in the symbol525  // table much more complicated than it is worth.526  //527  // FIXME: Revisit this when the dust settles.528 529  // Report errors for use of .indirect_symbol not in a symbol pointer section530  // or stub section.531  for (IndirectSymbolData &ISD : IndirectSymbols) {532    const MCSectionMachO &Section = static_cast<MCSectionMachO &>(*ISD.Section);533 534    if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&535        Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&536        Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&537        Section.getType() != MachO::S_SYMBOL_STUBS) {538      MCSymbol &Symbol = *ISD.Symbol;539      report_fatal_error("indirect symbol '" + Symbol.getName() +540                         "' not in a symbol pointer or stub section");541    }542  }543 544  // Bind non-lazy symbol pointers first.545  for (auto [IndirectIndex, ISD] : enumerate(IndirectSymbols)) {546    const auto &Section = static_cast<MCSectionMachO &>(*ISD.Section);547 548    if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&549        Section.getType() !=  MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)550      continue;551 552    // Initialize the section indirect symbol base, if necessary.553    IndirectSymBase.insert(std::make_pair(ISD.Section, IndirectIndex));554 555    Asm.registerSymbol(*ISD.Symbol);556  }557 558  // Then lazy symbol pointers and symbol stubs.559  for (auto [IndirectIndex, ISD] : enumerate(IndirectSymbols)) {560    const auto &Section = static_cast<MCSectionMachO &>(*ISD.Section);561 562    if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&563        Section.getType() != MachO::S_SYMBOL_STUBS)564      continue;565 566    // Initialize the section indirect symbol base, if necessary.567    IndirectSymBase.insert(std::make_pair(ISD.Section, IndirectIndex));568 569    // Set the symbol type to undefined lazy, but only on construction.570    //571    // FIXME: Do not hardcode.572    if (Asm.registerSymbol(*ISD.Symbol))573      ISD.Symbol->setReferenceTypeUndefinedLazy(true);574  }575}576 577/// computeSymbolTable - Compute the symbol table data578void MachObjectWriter::computeSymbolTable(579    MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData,580    std::vector<MachSymbolData> &ExternalSymbolData,581    std::vector<MachSymbolData> &UndefinedSymbolData) {582  // Build section lookup table.583  DenseMap<const MCSection*, uint8_t> SectionIndexMap;584  unsigned Index = 1;585  for (MCSection &Sec : Asm)586    SectionIndexMap[&Sec] = Index++;587 588  // Section indices begin from 1 in MachO. Only sections 1-255 can be indexed589  // into section symbols. Referencing a section with index larger than 255 will590  // not set n_sect for these symbols.591  if (Index > 255)592    getContext().reportError(SMLoc(), "Too many sections!");593 594  // Build the string table.595  for (const MCSymbol &Symbol : Asm.symbols()) {596    if (!static_cast<const MCSymbolMachO &>(Symbol).isSymbolLinkerVisible())597      continue;598 599    StringTable.add(Symbol.getName());600  }601  StringTable.finalize();602 603  // Build the symbol arrays but only for non-local symbols.604  //605  // The particular order that we collect and then sort the symbols is chosen to606  // match 'as'. Even though it doesn't matter for correctness, this is607  // important for letting us diff .o files.608  for (const MCSymbol &Symbol : Asm.symbols()) {609    auto &Sym = static_cast<const MCSymbolMachO &>(Symbol);610    // Ignore non-linker visible symbols.611    if (!Sym.isSymbolLinkerVisible())612      continue;613 614    if (!Sym.isExternal() && !Sym.isUndefined())615      continue;616 617    MachSymbolData MSD;618    MSD.Symbol = &Sym;619    MSD.StringIndex = StringTable.getOffset(Symbol.getName());620 621    if (Symbol.isUndefined()) {622      MSD.SectionIndex = 0;623      UndefinedSymbolData.push_back(MSD);624    } else if (Symbol.isAbsolute()) {625      MSD.SectionIndex = 0;626      ExternalSymbolData.push_back(MSD);627    } else {628      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());629      if (!MSD.SectionIndex)630        getContext().reportError(SMLoc(), "Invalid section index!");631      ExternalSymbolData.push_back(MSD);632    }633  }634 635  // Now add the data for local symbols.636  for (const MCSymbol &Symbol : Asm.symbols()) {637    auto &Sym = static_cast<const MCSymbolMachO &>(Symbol);638    // Ignore non-linker visible symbols.639    if (!Sym.isSymbolLinkerVisible())640      continue;641 642    if (Sym.isExternal() || Sym.isUndefined())643      continue;644 645    MachSymbolData MSD;646    MSD.Symbol = &Sym;647    MSD.StringIndex = StringTable.getOffset(Symbol.getName());648 649    if (Symbol.isAbsolute()) {650      MSD.SectionIndex = 0;651      LocalSymbolData.push_back(MSD);652    } else {653      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());654      if (!MSD.SectionIndex)655        getContext().reportError(SMLoc(), "Invalid section index!");656      LocalSymbolData.push_back(MSD);657    }658  }659 660  // External and undefined symbols are required to be in lexicographic order.661  llvm::sort(ExternalSymbolData);662  llvm::sort(UndefinedSymbolData);663 664  // Set the symbol indices.665  Index = 0;666  for (auto *SymbolData :667       {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})668    for (MachSymbolData &Entry : *SymbolData)669      Entry.Symbol->setIndex(Index++);670 671  for (const MCSection &Section : Asm) {672    for (RelAndSymbol &Rel : Relocations[&Section]) {673      if (!Rel.Sym)674        continue;675 676      // Set the Index and the IsExtern bit.677      unsigned Index = Rel.Sym->getIndex();678      assert(isInt<24>(Index));679      if (W.Endian == llvm::endianness::little)680        Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);681      else682        Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);683    }684  }685}686 687void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm) {688  // Assign layout order indices to sections.689  unsigned i = 0;690  // Compute the section layout order. Virtual sections must go last.691  for (MCSection &Sec : Asm) {692    if (!Sec.isBssSection()) {693      SectionOrder.push_back(&Sec);694      static_cast<MCSectionMachO &>(Sec).setLayoutOrder(i++);695    }696  }697  for (MCSection &Sec : Asm) {698    if (Sec.isBssSection()) {699      SectionOrder.push_back(&Sec);700      static_cast<MCSectionMachO &>(Sec).setLayoutOrder(i++);701    }702  }703 704  uint64_t StartAddress = 0;705  for (const MCSection *Sec : SectionOrder) {706    StartAddress = alignTo(StartAddress, Sec->getAlign());707    SectionAddress[Sec] = StartAddress;708    StartAddress += Asm.getSectionAddressSize(*Sec);709 710    // Explicitly pad the section to match the alignment requirements of the711    // following one. This is for 'gas' compatibility, it shouldn't712    /// strictly be necessary.713    StartAddress += getPaddingSize(Asm, Sec);714  }715}716 717void MachObjectWriter::executePostLayoutBinding() {718  computeSectionAddresses(*Asm);719 720  // Create symbol data for any indirect symbols.721  bindIndirectSymbols(*Asm);722}723 724bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(725    const MCSymbol &SymA, const MCFragment &FB, bool InSet,726    bool IsPCRel) const {727  if (InSet)728    return true;729 730  // The effective address is731  //     addr(atom(A)) + offset(A)732  //   - addr(atom(B)) - offset(B)733  // and the offsets are not relocatable, so the fixup is fully resolved when734  //  addr(atom(A)) - addr(atom(B)) == 0.735  const MCSymbol &SA = findAliasedSymbol(SymA);736  const MCSection &SecA = SA.getSection();737  const MCSection &SecB = *FB.getParent();738 739  if (IsPCRel) {740    // The simple (Darwin, except on x86_64) way of dealing with this was to741    // assume that any reference to a temporary symbol *must* be a temporary742    // symbol in the same atom, unless the sections differ. Therefore, any PCrel743    // relocation to a temporary symbol (in the same section) is fully744    // resolved. This also works in conjunction with absolutized .set, which745    // requires the compiler to use .set to absolutize the differences between746    // symbols which the compiler knows to be assembly time constants, so we747    // don't need to worry about considering symbol differences fully resolved.748    //749    // If the file isn't using sub-sections-via-symbols, we can make the750    // same assumptions about any symbol that we normally make about751    // assembler locals.752 753    bool hasReliableSymbolDifference = isX86_64();754    if (!hasReliableSymbolDifference) {755      if (!SA.isInSection() || &SecA != &SecB ||756          (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() &&757           SubsectionsViaSymbols))758        return false;759      return true;760    }761  }762 763  // If they are not in the same section, we can't compute the diff.764  if (&SecA != &SecB)765    return false;766 767  // If the atoms are the same, they are guaranteed to have the same address.768  return SA.getFragment()->getAtom() == FB.getAtom();769}770 771static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {772  switch (Type) {773  case MCVM_OSXVersionMin:     return MachO::LC_VERSION_MIN_MACOSX;774  case MCVM_IOSVersionMin:     return MachO::LC_VERSION_MIN_IPHONEOS;775  case MCVM_TvOSVersionMin:    return MachO::LC_VERSION_MIN_TVOS;776  case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS;777  }778  llvm_unreachable("Invalid mc version min type");779}780 781void MachObjectWriter::populateAddrSigSection(MCAssembler &Asm) {782  MCSection *AddrSigSection =783      getContext().getObjectFileInfo()->getAddrSigSection();784  unsigned Log2Size = is64Bit() ? 3 : 2;785  for (const MCSymbol *S : getAddrsigSyms()) {786    if (!S->isRegistered())787      continue;788    MachO::any_relocation_info MRE;789    MRE.r_word0 = 0;790    MRE.r_word1 = (Log2Size << 25) | (MachO::GENERIC_RELOC_VANILLA << 28);791    addRelocation(S, AddrSigSection, MRE);792  }793}794 795uint64_t MachObjectWriter::writeObject() {796  auto &Asm = *this->Asm;797  uint64_t StartOffset = W.OS.tell();798  auto NumBytesWritten = [&] { return W.OS.tell() - StartOffset; };799 800  populateAddrSigSection(Asm);801 802  // Compute symbol table information and bind symbol indices.803  computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,804                     UndefinedSymbolData);805 806  if (!CGProfile.empty()) {807    SmallString<0> Content;808    raw_svector_ostream OS(Content);809    for (const MCObjectWriter::CGProfileEntry &CGPE : CGProfile) {810      uint32_t FromIndex = CGPE.From->getSymbol().getIndex();811      uint32_t ToIndex = CGPE.To->getSymbol().getIndex();812      support::endian::write(OS, FromIndex, W.Endian);813      support::endian::write(OS, ToIndex, W.Endian);814      support::endian::write(OS, CGPE.Count, W.Endian);815    }816    MCSection *Sec = getContext().getMachOSection("__LLVM", "__cg_profile", 0,817                                                  SectionKind::getMetadata());818    llvm::copy(OS.str(), Sec->curFragList()->Head->getVarContents().data());819  }820 821  unsigned NumSections = Asm.end() - Asm.begin();822 823  // The section data starts after the header, the segment load command (and824  // section headers) and the symbol table.825  unsigned NumLoadCommands = 1;826  uint64_t LoadCommandsSize = is64Bit() ?827    sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):828    sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);829 830  // Add the deployment target version info load command size, if used.831  if (VersionInfo.Major != 0) {832    ++NumLoadCommands;833    if (VersionInfo.EmitBuildVersion)834      LoadCommandsSize += sizeof(MachO::build_version_command);835    else836      LoadCommandsSize += sizeof(MachO::version_min_command);837  }838 839  // Add the target variant version info load command size, if used.840  if (TargetVariantVersionInfo.Major != 0) {841    ++NumLoadCommands;842    assert(TargetVariantVersionInfo.EmitBuildVersion &&843           "target variant should use build version");844    LoadCommandsSize += sizeof(MachO::build_version_command);845  }846 847  // Add the data-in-code load command size, if used.848  unsigned NumDataRegions = DataRegions.size();849  if (NumDataRegions) {850    ++NumLoadCommands;851    LoadCommandsSize += sizeof(MachO::linkedit_data_command);852  }853 854  // Add the loh load command size, if used.855  uint64_t LOHRawSize = LOHContainer.getEmitSize(Asm, *this);856  uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4);857  if (LOHSize) {858    ++NumLoadCommands;859    LoadCommandsSize += sizeof(MachO::linkedit_data_command);860  }861 862  // Add the symbol table load command sizes, if used.863  unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +864    UndefinedSymbolData.size();865  if (NumSymbols) {866    NumLoadCommands += 2;867    LoadCommandsSize += (sizeof(MachO::symtab_command) +868                         sizeof(MachO::dysymtab_command));869  }870 871  // Add the linker option load commands sizes.872  for (const auto &Option : LinkerOptions) {873    ++NumLoadCommands;874    LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(Option, is64Bit());875  }876 877  // Compute the total size of the section data, as well as its file size and vm878  // size.879  uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) :880                               sizeof(MachO::mach_header)) + LoadCommandsSize;881  uint64_t SectionDataSize = 0;882  uint64_t SectionDataFileSize = 0;883  uint64_t VMSize = 0;884  for (const MCSection &Sec : Asm) {885    uint64_t Address = getSectionAddress(&Sec);886    uint64_t Size = Asm.getSectionAddressSize(Sec);887    uint64_t FileSize = Asm.getSectionFileSize(Sec);888    FileSize += getPaddingSize(Asm, &Sec);889 890    VMSize = std::max(VMSize, Address + Size);891 892    if (Sec.isBssSection())893      continue;894 895    SectionDataSize = std::max(SectionDataSize, Address + Size);896    SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);897  }898 899  // The section data is padded to pointer size bytes.900  //901  // FIXME: Is this machine dependent?902  unsigned SectionDataPadding =903      offsetToAlignment(SectionDataFileSize, is64Bit() ? Align(8) : Align(4));904  SectionDataFileSize += SectionDataPadding;905 906  // Write the prolog, starting with the header and load command...907  writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize,908              SubsectionsViaSymbols);909  uint32_t Prot =910      MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;911  writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart,912                          SectionDataSize, Prot, Prot);913 914  // ... and then the section headers.915  uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;916  for (const MCSection &Section : Asm) {917    const auto &Sec = static_cast<const MCSectionMachO &>(Section);918    std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];919    unsigned NumRelocs = Relocs.size();920    uint64_t SectionStart = SectionDataStart + getSectionAddress(&Sec);921    unsigned Flags = Sec.getTypeAndAttributes();922    if (Sec.hasInstructions())923      Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS;924    if (!cast<MCSectionMachO>(Sec).isBssSection() &&925        !isUInt<32>(SectionStart)) {926      getContext().reportError(927          SMLoc(), "cannot encode offset of section; object file too large");928      return NumBytesWritten();929    }930    if (NumRelocs && !isUInt<32>(RelocTableEnd)) {931      getContext().reportError(932          SMLoc(),933          "cannot encode offset of relocations; object file too large");934      return NumBytesWritten();935    }936    writeSection(Asm, Sec, getSectionAddress(&Sec), SectionStart, Flags,937                 RelocTableEnd, NumRelocs);938    RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);939  }940 941  // Write out the deployment target information, if it's available.942  auto EmitDeploymentTargetVersion =943      [&](const VersionInfoType &VersionInfo) {944        auto EncodeVersion = [](VersionTuple V) -> uint32_t {945          assert(!V.empty() && "empty version");946          unsigned Update = V.getSubminor().value_or(0);947          unsigned Minor = V.getMinor().value_or(0);948          assert(Update < 256 && "unencodable update target version");949          assert(Minor < 256 && "unencodable minor target version");950          assert(V.getMajor() < 65536 && "unencodable major target version");951          return Update | (Minor << 8) | (V.getMajor() << 16);952        };953        uint32_t EncodedVersion = EncodeVersion(VersionTuple(954            VersionInfo.Major, VersionInfo.Minor, VersionInfo.Update));955        uint32_t SDKVersion = !VersionInfo.SDKVersion.empty()956                                  ? EncodeVersion(VersionInfo.SDKVersion)957                                  : 0;958        if (VersionInfo.EmitBuildVersion) {959          // FIXME: Currently empty tools. Add clang version in the future.960          W.write<uint32_t>(MachO::LC_BUILD_VERSION);961          W.write<uint32_t>(sizeof(MachO::build_version_command));962          W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);963          W.write<uint32_t>(EncodedVersion);964          W.write<uint32_t>(SDKVersion);965          W.write<uint32_t>(0); // Empty tools list.966        } else {967          MachO::LoadCommandType LCType =968              getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);969          W.write<uint32_t>(LCType);970          W.write<uint32_t>(sizeof(MachO::version_min_command));971          W.write<uint32_t>(EncodedVersion);972          W.write<uint32_t>(SDKVersion);973        }974      };975  if (VersionInfo.Major != 0)976    EmitDeploymentTargetVersion(VersionInfo);977  if (TargetVariantVersionInfo.Major != 0)978    EmitDeploymentTargetVersion(TargetVariantVersionInfo);979 980  // Write the data-in-code load command, if used.981  uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;982  if (NumDataRegions) {983    uint64_t DataRegionsOffset = RelocTableEnd;984    uint64_t DataRegionsSize = NumDataRegions * 8;985    writeLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset,986                             DataRegionsSize);987  }988 989  // Write the loh load command, if used.990  uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize;991  if (LOHSize)992    writeLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT,993                             DataInCodeTableEnd, LOHSize);994 995  // Write the symbol table load command, if used.996  if (NumSymbols) {997    unsigned FirstLocalSymbol = 0;998    unsigned NumLocalSymbols = LocalSymbolData.size();999    unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;1000    unsigned NumExternalSymbols = ExternalSymbolData.size();1001    unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;1002    unsigned NumUndefinedSymbols = UndefinedSymbolData.size();1003    unsigned NumIndirectSymbols = IndirectSymbols.size();1004    unsigned NumSymTabSymbols =1005      NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;1006    uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;1007    uint64_t IndirectSymbolOffset = 0;1008 1009    // If used, the indirect symbols are written after the section data.1010    if (NumIndirectSymbols)1011      IndirectSymbolOffset = LOHTableEnd;1012 1013    // The symbol table is written after the indirect symbol data.1014    uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize;1015 1016    // The string table is written after symbol table.1017    uint64_t StringTableOffset =1018      SymbolTableOffset + NumSymTabSymbols * (is64Bit() ?1019                                              sizeof(MachO::nlist_64) :1020                                              sizeof(MachO::nlist));1021    writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,1022                           StringTableOffset, StringTable.getSize());1023 1024    writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,1025                             FirstExternalSymbol, NumExternalSymbols,1026                             FirstUndefinedSymbol, NumUndefinedSymbols,1027                             IndirectSymbolOffset, NumIndirectSymbols);1028  }1029 1030  // Write the linker options load commands.1031  for (const auto &Option : LinkerOptions)1032    writeLinkerOptionsLoadCommand(Option);1033 1034  // Write the actual section data.1035  for (const MCSection &Sec : Asm) {1036    Asm.writeSectionData(W.OS, &Sec);1037 1038    uint64_t Pad = getPaddingSize(Asm, &Sec);1039    W.OS.write_zeros(Pad);1040  }1041 1042  // Write the extra padding.1043  W.OS.write_zeros(SectionDataPadding);1044 1045  // Write the relocation entries.1046  for (const MCSection &Sec : Asm) {1047    // Write the section relocation entries, in reverse order to match 'as'1048    // (approximately, the exact algorithm is more complicated than this).1049    std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];1050    for (const RelAndSymbol &Rel : llvm::reverse(Relocs)) {1051      W.write<uint32_t>(Rel.MRE.r_word0);1052      W.write<uint32_t>(Rel.MRE.r_word1);1053    }1054  }1055 1056  // Write out the data-in-code region payload, if there is one.1057  for (DataRegionData Data : DataRegions) {1058    uint64_t Start = getSymbolAddress(*Data.Start);1059    uint64_t End;1060    if (Data.End)1061      End = getSymbolAddress(*Data.End);1062    else1063      report_fatal_error("Data region not terminated");1064 1065    LLVM_DEBUG(dbgs() << "data in code region-- kind: " << Data.Kind1066                      << "  start: " << Start << "(" << Data.Start->getName()1067                      << ")" << "  end: " << End << "(" << Data.End->getName()1068                      << ")" << "  size: " << End - Start << "\n");1069    W.write<uint32_t>(Start);1070    W.write<uint16_t>(End - Start);1071    W.write<uint16_t>(Data.Kind);1072  }1073 1074  // Write out the loh commands, if there is one.1075  if (LOHSize) {1076#ifndef NDEBUG1077    unsigned Start = W.OS.tell();1078#endif1079    LOHContainer.emit(Asm, *this);1080    // Pad to a multiple of the pointer size.1081    W.OS.write_zeros(1082        offsetToAlignment(LOHRawSize, is64Bit() ? Align(8) : Align(4)));1083    assert(W.OS.tell() - Start == LOHSize);1084  }1085 1086  // Write the symbol table data, if used.1087  if (NumSymbols) {1088    // Write the indirect symbol entries.1089    for (auto &ISD : IndirectSymbols) {1090      // Indirect symbols in the non-lazy symbol pointer section have some1091      // special handling.1092      const MCSectionMachO &Section =1093          static_cast<const MCSectionMachO &>(*ISD.Section);1094      if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) {1095        // If this symbol is defined and internal, mark it as such.1096        if (ISD.Symbol->isDefined() && !ISD.Symbol->isExternal()) {1097          uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;1098          if (ISD.Symbol->isAbsolute())1099            Flags |= MachO::INDIRECT_SYMBOL_ABS;1100          W.write<uint32_t>(Flags);1101          continue;1102        }1103      }1104 1105      W.write<uint32_t>(ISD.Symbol->getIndex());1106    }1107 1108    // FIXME: Check that offsets match computed ones.1109 1110    // Write the symbol table entries.1111    for (auto *SymbolData :1112         {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})1113      for (MachSymbolData &Entry : *SymbolData)1114        writeNlist(Entry, Asm);1115 1116    // Write the string table.1117    StringTable.write(W.OS);1118  }1119 1120  return NumBytesWritten();1121}1122