1205407Srdivacky//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//
2205407Srdivacky//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6205407Srdivacky//
7205407Srdivacky//===----------------------------------------------------------------------===//
8205407Srdivacky
9321369Sdim#include "llvm/ADT/DenseMap.h"
10205407Srdivacky#include "llvm/ADT/Twine.h"
11321369Sdim#include "llvm/ADT/iterator_range.h"
12321369Sdim#include "llvm/BinaryFormat/MachO.h"
13226633Sdim#include "llvm/MC/MCAsmBackend.h"
14206083Srdivacky#include "llvm/MC/MCAsmLayout.h"
15249423Sdim#include "llvm/MC/MCAssembler.h"
16353358Sdim#include "llvm/MC/MCContext.h"
17321369Sdim#include "llvm/MC/MCDirectives.h"
18205407Srdivacky#include "llvm/MC/MCExpr.h"
19234353Sdim#include "llvm/MC/MCFixupKindInfo.h"
20321369Sdim#include "llvm/MC/MCFragment.h"
21321369Sdim#include "llvm/MC/MCMachObjectWriter.h"
22205407Srdivacky#include "llvm/MC/MCObjectWriter.h"
23321369Sdim#include "llvm/MC/MCSection.h"
24205407Srdivacky#include "llvm/MC/MCSectionMachO.h"
25321369Sdim#include "llvm/MC/MCSymbol.h"
26288943Sdim#include "llvm/MC/MCSymbolMachO.h"
27205407Srdivacky#include "llvm/MC/MCValue.h"
28360784Sdim#include "llvm/Support/Alignment.h"
29321369Sdim#include "llvm/Support/Casting.h"
30239462Sdim#include "llvm/Support/Debug.h"
31205407Srdivacky#include "llvm/Support/ErrorHandling.h"
32321369Sdim#include "llvm/Support/MathExtras.h"
33288943Sdim#include "llvm/Support/raw_ostream.h"
34321369Sdim#include <algorithm>
35321369Sdim#include <cassert>
36321369Sdim#include <cstdint>
37321369Sdim#include <string>
38321369Sdim#include <utility>
39205407Srdivacky#include <vector>
40321369Sdim
41205407Srdivackyusing namespace llvm;
42205407Srdivacky
43276479Sdim#define DEBUG_TYPE "mc"
44276479Sdim
45249423Sdimvoid MachObjectWriter::reset() {
46249423Sdim  Relocations.clear();
47249423Sdim  IndirectSymBase.clear();
48249423Sdim  StringTable.clear();
49249423Sdim  LocalSymbolData.clear();
50249423Sdim  ExternalSymbolData.clear();
51249423Sdim  UndefinedSymbolData.clear();
52249423Sdim  MCObjectWriter::reset();
53249423Sdim}
54249423Sdim
55288943Sdimbool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) {
56208599Srdivacky  // Undefined symbols are always extern.
57288943Sdim  if (S.isUndefined())
58208599Srdivacky    return true;
59208599Srdivacky
60208599Srdivacky  // References to weak definitions require external relocation entries; the
61208599Srdivacky  // definition may not always be the one in the same object file.
62288943Sdim  if (cast<MCSymbolMachO>(S).isWeakDefinition())
63208599Srdivacky    return true;
64208599Srdivacky
65208599Srdivacky  // Otherwise, we can use an internal relocation.
66208599Srdivacky  return false;
67208599Srdivacky}
68208599Srdivacky
69224145Sdimbool MachObjectWriter::
70224145SdimMachSymbolData::operator<(const MachSymbolData &RHS) const {
71288943Sdim  return Symbol->getName() < RHS.Symbol->getName();
72224145Sdim}
73205407Srdivacky
74224145Sdimbool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
75224145Sdim  const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo(
76224145Sdim    (MCFixupKind) Kind);
77205407Srdivacky
78224145Sdim  return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
79224145Sdim}
80205407Srdivacky
81224145Sdimuint64_t MachObjectWriter::getFragmentAddress(const MCFragment *Fragment,
82224145Sdim                                              const MCAsmLayout &Layout) const {
83224145Sdim  return getSectionAddress(Fragment->getParent()) +
84288943Sdim         Layout.getFragmentOffset(Fragment);
85224145Sdim}
86218893Sdim
87288943Sdimuint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S,
88224145Sdim                                            const MCAsmLayout &Layout) const {
89224145Sdim  // If this is a variable, then recursively evaluate now.
90224145Sdim  if (S.isVariable()) {
91243830Sdim    if (const MCConstantExpr *C =
92243830Sdim          dyn_cast<const MCConstantExpr>(S.getVariableValue()))
93243830Sdim      return C->getValue();
94243830Sdim
95224145Sdim    MCValue Target;
96288943Sdim    if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Layout, nullptr))
97224145Sdim      report_fatal_error("unable to evaluate offset for variable '" +
98224145Sdim                         S.getName() + "'");
99205407Srdivacky
100224145Sdim    // Verify that any used symbols are defined.
101224145Sdim    if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined())
102224145Sdim      report_fatal_error("unable to evaluate offset to undefined symbol '" +
103224145Sdim                         Target.getSymA()->getSymbol().getName() + "'");
104224145Sdim    if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined())
105224145Sdim      report_fatal_error("unable to evaluate offset to undefined symbol '" +
106224145Sdim                         Target.getSymB()->getSymbol().getName() + "'");
107205407Srdivacky
108224145Sdim    uint64_t Address = Target.getConstant();
109224145Sdim    if (Target.getSymA())
110288943Sdim      Address += getSymbolAddress(Target.getSymA()->getSymbol(), Layout);
111224145Sdim    if (Target.getSymB())
112288943Sdim      Address += getSymbolAddress(Target.getSymB()->getSymbol(), Layout);
113224145Sdim    return Address;
114218893Sdim  }
115205407Srdivacky
116288943Sdim  return getSectionAddress(S.getFragment()->getParent()) +
117288943Sdim         Layout.getSymbolOffset(S);
118224145Sdim}
119218893Sdim
120288943Sdimuint64_t MachObjectWriter::getPaddingSize(const MCSection *Sec,
121224145Sdim                                          const MCAsmLayout &Layout) const {
122288943Sdim  uint64_t EndAddr = getSectionAddress(Sec) + Layout.getSectionAddressSize(Sec);
123288943Sdim  unsigned Next = Sec->getLayoutOrder() + 1;
124224145Sdim  if (Next >= Layout.getSectionOrder().size())
125224145Sdim    return 0;
126221345Sdim
127288943Sdim  const MCSection &NextSec = *Layout.getSectionOrder()[Next];
128288943Sdim  if (NextSec.isVirtualSection())
129224145Sdim    return 0;
130360784Sdim  return offsetToAlignment(EndAddr, Align(NextSec.getAlignment()));
131224145Sdim}
132221345Sdim
133296417Sdimvoid MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
134296417Sdim                                   unsigned NumLoadCommands,
135224145Sdim                                   unsigned LoadCommandsSize,
136224145Sdim                                   bool SubsectionsViaSymbols) {
137224145Sdim  uint32_t Flags = 0;
138221345Sdim
139224145Sdim  if (SubsectionsViaSymbols)
140261991Sdim    Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
141221345Sdim
142224145Sdim  // struct mach_header (28 bytes) or
143224145Sdim  // struct mach_header_64 (32 bytes)
144218893Sdim
145341825Sdim  uint64_t Start = W.OS.tell();
146224145Sdim  (void) Start;
147218893Sdim
148341825Sdim  W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
149218893Sdim
150341825Sdim  W.write<uint32_t>(TargetObjectWriter->getCPUType());
151341825Sdim  W.write<uint32_t>(TargetObjectWriter->getCPUSubtype());
152205407Srdivacky
153341825Sdim  W.write<uint32_t>(Type);
154341825Sdim  W.write<uint32_t>(NumLoadCommands);
155341825Sdim  W.write<uint32_t>(LoadCommandsSize);
156341825Sdim  W.write<uint32_t>(Flags);
157224145Sdim  if (is64Bit())
158341825Sdim    W.write<uint32_t>(0); // reserved
159218893Sdim
160341825Sdim  assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64)
161341825Sdim                                           : sizeof(MachO::mach_header)));
162224145Sdim}
163205407Srdivacky
164341825Sdimvoid MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) {
165341825Sdim  assert(Size >= Str.size());
166341825Sdim  W.OS << Str;
167341825Sdim  W.OS.write_zeros(Size - Str.size());
168341825Sdim}
169341825Sdim
170288943Sdim/// writeSegmentLoadCommand - Write a segment load command.
171224145Sdim///
172243830Sdim/// \param NumSections The number of sections in this segment.
173243830Sdim/// \param SectionDataSize The total size of the sections.
174296417Sdimvoid MachObjectWriter::writeSegmentLoadCommand(
175296417Sdim    StringRef Name, unsigned NumSections, uint64_t VMAddr, uint64_t VMSize,
176296417Sdim    uint64_t SectionDataStartOffset, uint64_t SectionDataSize, uint32_t MaxProt,
177296417Sdim    uint32_t InitProt) {
178224145Sdim  // struct segment_command (56 bytes) or
179224145Sdim  // struct segment_command_64 (72 bytes)
180218893Sdim
181341825Sdim  uint64_t Start = W.OS.tell();
182224145Sdim  (void) Start;
183205407Srdivacky
184224145Sdim  unsigned SegmentLoadCommandSize =
185261991Sdim    is64Bit() ? sizeof(MachO::segment_command_64):
186261991Sdim    sizeof(MachO::segment_command);
187341825Sdim  W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
188341825Sdim  W.write<uint32_t>(SegmentLoadCommandSize +
189261991Sdim          NumSections * (is64Bit() ? sizeof(MachO::section_64) :
190261991Sdim                         sizeof(MachO::section)));
191205407Srdivacky
192341825Sdim  writeWithPadding(Name, 16);
193224145Sdim  if (is64Bit()) {
194341825Sdim    W.write<uint64_t>(VMAddr);                 // vmaddr
195341825Sdim    W.write<uint64_t>(VMSize); // vmsize
196341825Sdim    W.write<uint64_t>(SectionDataStartOffset); // file offset
197341825Sdim    W.write<uint64_t>(SectionDataSize); // file size
198224145Sdim  } else {
199341825Sdim    W.write<uint32_t>(VMAddr);                 // vmaddr
200341825Sdim    W.write<uint32_t>(VMSize); // vmsize
201341825Sdim    W.write<uint32_t>(SectionDataStartOffset); // file offset
202341825Sdim    W.write<uint32_t>(SectionDataSize); // file size
203205407Srdivacky  }
204261991Sdim  // maxprot
205341825Sdim  W.write<uint32_t>(MaxProt);
206261991Sdim  // initprot
207341825Sdim  W.write<uint32_t>(InitProt);
208341825Sdim  W.write<uint32_t>(NumSections);
209341825Sdim  W.write<uint32_t>(0); // flags
210205407Srdivacky
211341825Sdim  assert(W.OS.tell() - Start == SegmentLoadCommandSize);
212224145Sdim}
213205407Srdivacky
214296417Sdimvoid MachObjectWriter::writeSection(const MCAsmLayout &Layout,
215296417Sdim                                    const MCSection &Sec, uint64_t VMAddr,
216296417Sdim                                    uint64_t FileOffset, unsigned Flags,
217224145Sdim                                    uint64_t RelocationsStart,
218224145Sdim                                    unsigned NumRelocations) {
219288943Sdim  uint64_t SectionSize = Layout.getSectionAddressSize(&Sec);
220288943Sdim  const MCSectionMachO &Section = cast<MCSectionMachO>(Sec);
221205407Srdivacky
222224145Sdim  // The offset is unused for virtual sections.
223288943Sdim  if (Section.isVirtualSection()) {
224288943Sdim    assert(Layout.getSectionFileSize(&Sec) == 0 && "Invalid file size!");
225224145Sdim    FileOffset = 0;
226205407Srdivacky  }
227205407Srdivacky
228224145Sdim  // struct section (68 bytes) or
229224145Sdim  // struct section_64 (80 bytes)
230206083Srdivacky
231341825Sdim  uint64_t Start = W.OS.tell();
232224145Sdim  (void) Start;
233205407Srdivacky
234341825Sdim  writeWithPadding(Section.getSectionName(), 16);
235341825Sdim  writeWithPadding(Section.getSegmentName(), 16);
236224145Sdim  if (is64Bit()) {
237341825Sdim    W.write<uint64_t>(VMAddr);      // address
238341825Sdim    W.write<uint64_t>(SectionSize); // size
239224145Sdim  } else {
240341825Sdim    W.write<uint32_t>(VMAddr);      // address
241341825Sdim    W.write<uint32_t>(SectionSize); // size
242205407Srdivacky  }
243341825Sdim  W.write<uint32_t>(FileOffset);
244205407Srdivacky
245288943Sdim  assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!");
246341825Sdim  W.write<uint32_t>(Log2_32(Section.getAlignment()));
247341825Sdim  W.write<uint32_t>(NumRelocations ? RelocationsStart : 0);
248341825Sdim  W.write<uint32_t>(NumRelocations);
249341825Sdim  W.write<uint32_t>(Flags);
250341825Sdim  W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1
251341825Sdim  W.write<uint32_t>(Section.getStubSize()); // reserved2
252224145Sdim  if (is64Bit())
253341825Sdim    W.write<uint32_t>(0); // reserved3
254205407Srdivacky
255341825Sdim  assert(W.OS.tell() - Start ==
256296417Sdim         (is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));
257224145Sdim}
258205407Srdivacky
259288943Sdimvoid MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,
260224145Sdim                                              uint32_t NumSymbols,
261224145Sdim                                              uint32_t StringTableOffset,
262224145Sdim                                              uint32_t StringTableSize) {
263224145Sdim  // struct symtab_command (24 bytes)
264205407Srdivacky
265341825Sdim  uint64_t Start = W.OS.tell();
266224145Sdim  (void) Start;
267205407Srdivacky
268341825Sdim  W.write<uint32_t>(MachO::LC_SYMTAB);
269341825Sdim  W.write<uint32_t>(sizeof(MachO::symtab_command));
270341825Sdim  W.write<uint32_t>(SymbolOffset);
271341825Sdim  W.write<uint32_t>(NumSymbols);
272341825Sdim  W.write<uint32_t>(StringTableOffset);
273341825Sdim  W.write<uint32_t>(StringTableSize);
274205407Srdivacky
275341825Sdim  assert(W.OS.tell() - Start == sizeof(MachO::symtab_command));
276224145Sdim}
277205407Srdivacky
278288943Sdimvoid MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
279224145Sdim                                                uint32_t NumLocalSymbols,
280224145Sdim                                                uint32_t FirstExternalSymbol,
281224145Sdim                                                uint32_t NumExternalSymbols,
282224145Sdim                                                uint32_t FirstUndefinedSymbol,
283224145Sdim                                                uint32_t NumUndefinedSymbols,
284224145Sdim                                                uint32_t IndirectSymbolOffset,
285224145Sdim                                                uint32_t NumIndirectSymbols) {
286224145Sdim  // struct dysymtab_command (80 bytes)
287205407Srdivacky
288341825Sdim  uint64_t Start = W.OS.tell();
289224145Sdim  (void) Start;
290205407Srdivacky
291341825Sdim  W.write<uint32_t>(MachO::LC_DYSYMTAB);
292341825Sdim  W.write<uint32_t>(sizeof(MachO::dysymtab_command));
293341825Sdim  W.write<uint32_t>(FirstLocalSymbol);
294341825Sdim  W.write<uint32_t>(NumLocalSymbols);
295341825Sdim  W.write<uint32_t>(FirstExternalSymbol);
296341825Sdim  W.write<uint32_t>(NumExternalSymbols);
297341825Sdim  W.write<uint32_t>(FirstUndefinedSymbol);
298341825Sdim  W.write<uint32_t>(NumUndefinedSymbols);
299341825Sdim  W.write<uint32_t>(0); // tocoff
300341825Sdim  W.write<uint32_t>(0); // ntoc
301341825Sdim  W.write<uint32_t>(0); // modtaboff
302341825Sdim  W.write<uint32_t>(0); // nmodtab
303341825Sdim  W.write<uint32_t>(0); // extrefsymoff
304341825Sdim  W.write<uint32_t>(0); // nextrefsyms
305341825Sdim  W.write<uint32_t>(IndirectSymbolOffset);
306341825Sdim  W.write<uint32_t>(NumIndirectSymbols);
307341825Sdim  W.write<uint32_t>(0); // extreloff
308341825Sdim  W.write<uint32_t>(0); // nextrel
309341825Sdim  W.write<uint32_t>(0); // locreloff
310341825Sdim  W.write<uint32_t>(0); // nlocrel
311205407Srdivacky
312341825Sdim  assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command));
313224145Sdim}
314205407Srdivacky
315276479SdimMachObjectWriter::MachSymbolData *
316276479SdimMachObjectWriter::findSymbolData(const MCSymbol &Sym) {
317288943Sdim  for (auto *SymbolData :
318288943Sdim       {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
319288943Sdim    for (MachSymbolData &Entry : *SymbolData)
320288943Sdim      if (Entry.Symbol == &Sym)
321288943Sdim        return &Entry;
322276479Sdim
323276479Sdim  return nullptr;
324276479Sdim}
325276479Sdim
326288943Sdimconst MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const {
327288943Sdim  const MCSymbol *S = &Sym;
328288943Sdim  while (S->isVariable()) {
329288943Sdim    const MCExpr *Value = S->getVariableValue();
330288943Sdim    const auto *Ref = dyn_cast<MCSymbolRefExpr>(Value);
331288943Sdim    if (!Ref)
332288943Sdim      return *S;
333288943Sdim    S = &Ref->getSymbol();
334288943Sdim  }
335288943Sdim  return *S;
336288943Sdim}
337288943Sdim
338288943Sdimvoid MachObjectWriter::writeNlist(MachSymbolData &MSD,
339224145Sdim                                  const MCAsmLayout &Layout) {
340288943Sdim  const MCSymbol *Symbol = MSD.Symbol;
341288943Sdim  const MCSymbol &Data = *Symbol;
342288943Sdim  const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol);
343276479Sdim  uint8_t SectionIndex = MSD.SectionIndex;
344224145Sdim  uint8_t Type = 0;
345226633Sdim  uint64_t Address = 0;
346276479Sdim  bool IsAlias = Symbol != AliasedSymbol;
347205407Srdivacky
348288943Sdim  const MCSymbol &OrigSymbol = *Symbol;
349276479Sdim  MachSymbolData *AliaseeInfo;
350276479Sdim  if (IsAlias) {
351276479Sdim    AliaseeInfo = findSymbolData(*AliasedSymbol);
352276479Sdim    if (AliaseeInfo)
353276479Sdim      SectionIndex = AliaseeInfo->SectionIndex;
354276479Sdim    Symbol = AliasedSymbol;
355309124Sdim    // FIXME: Should this update Data as well?
356276479Sdim  }
357276479Sdim
358224145Sdim  // Set the N_TYPE bits. See <mach-o/nlist.h>.
359206083Srdivacky  //
360224145Sdim  // FIXME: Are the prebound or indirect fields possible here?
361276479Sdim  if (IsAlias && Symbol->isUndefined())
362276479Sdim    Type = MachO::N_INDR;
363276479Sdim  else if (Symbol->isUndefined())
364261991Sdim    Type = MachO::N_UNDF;
365276479Sdim  else if (Symbol->isAbsolute())
366261991Sdim    Type = MachO::N_ABS;
367224145Sdim  else
368261991Sdim    Type = MachO::N_SECT;
369206083Srdivacky
370224145Sdim  // FIXME: Set STAB bits.
371205407Srdivacky
372224145Sdim  if (Data.isPrivateExtern())
373261991Sdim    Type |= MachO::N_PEXT;
374205407Srdivacky
375224145Sdim  // Set external bit.
376276479Sdim  if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))
377261991Sdim    Type |= MachO::N_EXT;
378205407Srdivacky
379224145Sdim  // Compute the symbol address.
380276479Sdim  if (IsAlias && Symbol->isUndefined())
381276479Sdim    Address = AliaseeInfo->StringIndex;
382276479Sdim  else if (Symbol->isDefined())
383288943Sdim    Address = getSymbolAddress(OrigSymbol, Layout);
384288943Sdim  else if (Symbol->isCommon()) {
385224145Sdim    // Common symbols are encoded with the size in the address
386224145Sdim    // field, and their alignment in the flags.
387288943Sdim    Address = Symbol->getCommonSize();
388205407Srdivacky  }
389205407Srdivacky
390224145Sdim  // struct nlist (12 bytes)
391205407Srdivacky
392341825Sdim  W.write<uint32_t>(MSD.StringIndex);
393341825Sdim  W.OS << char(Type);
394341825Sdim  W.OS << char(SectionIndex);
395205407Srdivacky
396224145Sdim  // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
397224145Sdim  // value.
398309124Sdim  bool EncodeAsAltEntry =
399309124Sdim    IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
400341825Sdim  W.write<uint16_t>(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
401224145Sdim  if (is64Bit())
402341825Sdim    W.write<uint64_t>(Address);
403224145Sdim  else
404341825Sdim    W.write<uint32_t>(Address);
405224145Sdim}
406205407Srdivacky
407288943Sdimvoid MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
408239462Sdim                                                uint32_t DataOffset,
409239462Sdim                                                uint32_t DataSize) {
410341825Sdim  uint64_t Start = W.OS.tell();
411239462Sdim  (void) Start;
412239462Sdim
413341825Sdim  W.write<uint32_t>(Type);
414341825Sdim  W.write<uint32_t>(sizeof(MachO::linkedit_data_command));
415341825Sdim  W.write<uint32_t>(DataOffset);
416341825Sdim  W.write<uint32_t>(DataSize);
417239462Sdim
418341825Sdim  assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command));
419239462Sdim}
420239462Sdim
421249423Sdimstatic unsigned ComputeLinkerOptionsLoadCommandSize(
422249423Sdim  const std::vector<std::string> &Options, bool is64Bit)
423249423Sdim{
424280031Sdim  unsigned Size = sizeof(MachO::linker_option_command);
425288943Sdim  for (const std::string &Option : Options)
426288943Sdim    Size += Option.size() + 1;
427309124Sdim  return alignTo(Size, is64Bit ? 8 : 4);
428249423Sdim}
429239462Sdim
430288943Sdimvoid MachObjectWriter::writeLinkerOptionsLoadCommand(
431249423Sdim  const std::vector<std::string> &Options)
432249423Sdim{
433249423Sdim  unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());
434341825Sdim  uint64_t Start = W.OS.tell();
435249423Sdim  (void) Start;
436249423Sdim
437341825Sdim  W.write<uint32_t>(MachO::LC_LINKER_OPTION);
438341825Sdim  W.write<uint32_t>(Size);
439341825Sdim  W.write<uint32_t>(Options.size());
440280031Sdim  uint64_t BytesWritten = sizeof(MachO::linker_option_command);
441288943Sdim  for (const std::string &Option : Options) {
442249423Sdim    // Write each string, including the null byte.
443341825Sdim    W.OS << Option << '\0';
444249423Sdim    BytesWritten += Option.size() + 1;
445249423Sdim  }
446249423Sdim
447249423Sdim  // Pad to a multiple of the pointer size.
448360784Sdim  W.OS.write_zeros(
449360784Sdim      offsetToAlignment(BytesWritten, is64Bit() ? Align(8) : Align(4)));
450249423Sdim
451341825Sdim  assert(W.OS.tell() - Start == Size);
452249423Sdim}
453249423Sdim
454353358Sdimstatic bool isFixupTargetValid(const MCValue &Target) {
455353358Sdim  // Target is (LHS - RHS + cst).
456353358Sdim  // We don't support the form where LHS is null: -RHS + cst
457353358Sdim  if (!Target.getSymA() && Target.getSymB())
458353358Sdim    return false;
459353358Sdim  return true;
460353358Sdim}
461353358Sdim
462288943Sdimvoid MachObjectWriter::recordRelocation(MCAssembler &Asm,
463224145Sdim                                        const MCAsmLayout &Layout,
464224145Sdim                                        const MCFragment *Fragment,
465288943Sdim                                        const MCFixup &Fixup, MCValue Target,
466321369Sdim                                        uint64_t &FixedValue) {
467353358Sdim  if (!isFixupTargetValid(Target)) {
468353358Sdim    Asm.getContext().reportError(Fixup.getLoc(),
469353358Sdim                                 "unsupported relocation expression");
470353358Sdim    return;
471353358Sdim  }
472353358Sdim
473288943Sdim  TargetObjectWriter->recordRelocation(this, Asm, Layout, Fragment, Fixup,
474224145Sdim                                       Target, FixedValue);
475224145Sdim}
476205407Srdivacky
477288943Sdimvoid MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) {
478224145Sdim  // This is the point where 'as' creates actual symbols for indirect symbols
479224145Sdim  // (in the following two passes). It would be easier for us to do this sooner
480224145Sdim  // when we see the attribute, but that makes getting the order in the symbol
481224145Sdim  // table much more complicated than it is worth.
482224145Sdim  //
483224145Sdim  // FIXME: Revisit this when the dust settles.
484205407Srdivacky
485261991Sdim  // Report errors for use of .indirect_symbol not in a symbol pointer section
486261991Sdim  // or stub section.
487261991Sdim  for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
488261991Sdim         ie = Asm.indirect_symbol_end(); it != ie; ++it) {
489288943Sdim    const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
490261991Sdim
491276479Sdim    if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
492276479Sdim        Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
493309124Sdim        Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
494276479Sdim        Section.getType() != MachO::S_SYMBOL_STUBS) {
495296417Sdim      MCSymbol &Symbol = *it->Symbol;
496296417Sdim      report_fatal_error("indirect symbol '" + Symbol.getName() +
497296417Sdim                         "' not in a symbol pointer or stub section");
498261991Sdim    }
499261991Sdim  }
500261991Sdim
501276479Sdim  // Bind non-lazy symbol pointers first.
502224145Sdim  unsigned IndirectIndex = 0;
503224145Sdim  for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
504224145Sdim         ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
505288943Sdim    const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
506205407Srdivacky
507309124Sdim    if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
508309124Sdim        Section.getType() !=  MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
509224145Sdim      continue;
510205407Srdivacky
511224145Sdim    // Initialize the section indirect symbol base, if necessary.
512288943Sdim    IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
513205407Srdivacky
514288943Sdim    Asm.registerSymbol(*it->Symbol);
515205407Srdivacky  }
516205407Srdivacky
517224145Sdim  // Then lazy symbol pointers and symbol stubs.
518224145Sdim  IndirectIndex = 0;
519224145Sdim  for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
520224145Sdim         ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
521288943Sdim    const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
522218893Sdim
523276479Sdim    if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
524276479Sdim        Section.getType() != MachO::S_SYMBOL_STUBS)
525224145Sdim      continue;
526218893Sdim
527224145Sdim    // Initialize the section indirect symbol base, if necessary.
528288943Sdim    IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
529218893Sdim
530224145Sdim    // Set the symbol type to undefined lazy, but only on construction.
531224145Sdim    //
532224145Sdim    // FIXME: Do not hardcode.
533224145Sdim    bool Created;
534288943Sdim    Asm.registerSymbol(*it->Symbol, &Created);
535224145Sdim    if (Created)
536288943Sdim      cast<MCSymbolMachO>(it->Symbol)->setReferenceTypeUndefinedLazy(true);
537218893Sdim  }
538224145Sdim}
539218893Sdim
540288943Sdim/// computeSymbolTable - Compute the symbol table data
541288943Sdimvoid MachObjectWriter::computeSymbolTable(
542280031Sdim    MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData,
543280031Sdim    std::vector<MachSymbolData> &ExternalSymbolData,
544280031Sdim    std::vector<MachSymbolData> &UndefinedSymbolData) {
545224145Sdim  // Build section lookup table.
546224145Sdim  DenseMap<const MCSection*, uint8_t> SectionIndexMap;
547224145Sdim  unsigned Index = 1;
548224145Sdim  for (MCAssembler::iterator it = Asm.begin(),
549224145Sdim         ie = Asm.end(); it != ie; ++it, ++Index)
550288943Sdim    SectionIndexMap[&*it] = Index;
551224145Sdim  assert(Index <= 256 && "Too many sections!");
552218893Sdim
553280031Sdim  // Build the string table.
554288943Sdim  for (const MCSymbol &Symbol : Asm.symbols()) {
555280031Sdim    if (!Asm.isSymbolLinkerVisible(Symbol))
556280031Sdim      continue;
557218893Sdim
558280031Sdim    StringTable.add(Symbol.getName());
559280031Sdim  }
560296417Sdim  StringTable.finalize();
561280031Sdim
562280031Sdim  // Build the symbol arrays but only for non-local symbols.
563224145Sdim  //
564280031Sdim  // The particular order that we collect and then sort the symbols is chosen to
565280031Sdim  // match 'as'. Even though it doesn't matter for correctness, this is
566280031Sdim  // important for letting us diff .o files.
567288943Sdim  for (const MCSymbol &Symbol : Asm.symbols()) {
568224145Sdim    // Ignore non-linker visible symbols.
569280031Sdim    if (!Asm.isSymbolLinkerVisible(Symbol))
570224145Sdim      continue;
571218893Sdim
572288943Sdim    if (!Symbol.isExternal() && !Symbol.isUndefined())
573224145Sdim      continue;
574218893Sdim
575224145Sdim    MachSymbolData MSD;
576288943Sdim    MSD.Symbol = &Symbol;
577280031Sdim    MSD.StringIndex = StringTable.getOffset(Symbol.getName());
578218893Sdim
579224145Sdim    if (Symbol.isUndefined()) {
580224145Sdim      MSD.SectionIndex = 0;
581224145Sdim      UndefinedSymbolData.push_back(MSD);
582224145Sdim    } else if (Symbol.isAbsolute()) {
583224145Sdim      MSD.SectionIndex = 0;
584224145Sdim      ExternalSymbolData.push_back(MSD);
585210299Sed    } else {
586224145Sdim      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
587224145Sdim      assert(MSD.SectionIndex && "Invalid section index!");
588224145Sdim      ExternalSymbolData.push_back(MSD);
589210299Sed    }
590218893Sdim  }
591218893Sdim
592224145Sdim  // Now add the data for local symbols.
593288943Sdim  for (const MCSymbol &Symbol : Asm.symbols()) {
594224145Sdim    // Ignore non-linker visible symbols.
595280031Sdim    if (!Asm.isSymbolLinkerVisible(Symbol))
596224145Sdim      continue;
597218893Sdim
598288943Sdim    if (Symbol.isExternal() || Symbol.isUndefined())
599224145Sdim      continue;
600218893Sdim
601224145Sdim    MachSymbolData MSD;
602288943Sdim    MSD.Symbol = &Symbol;
603280031Sdim    MSD.StringIndex = StringTable.getOffset(Symbol.getName());
604218893Sdim
605224145Sdim    if (Symbol.isAbsolute()) {
606224145Sdim      MSD.SectionIndex = 0;
607224145Sdim      LocalSymbolData.push_back(MSD);
608221345Sdim    } else {
609224145Sdim      MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
610224145Sdim      assert(MSD.SectionIndex && "Invalid section index!");
611224145Sdim      LocalSymbolData.push_back(MSD);
612218893Sdim    }
613210299Sed  }
614218893Sdim
615224145Sdim  // External and undefined symbols are required to be in lexicographic order.
616344779Sdim  llvm::sort(ExternalSymbolData);
617344779Sdim  llvm::sort(UndefinedSymbolData);
618205407Srdivacky
619224145Sdim  // Set the symbol indices.
620224145Sdim  Index = 0;
621288943Sdim  for (auto *SymbolData :
622288943Sdim       {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
623288943Sdim    for (MachSymbolData &Entry : *SymbolData)
624288943Sdim      Entry.Symbol->setIndex(Index++);
625288943Sdim
626288943Sdim  for (const MCSection &Section : Asm) {
627288943Sdim    for (RelAndSymbol &Rel : Relocations[&Section]) {
628288943Sdim      if (!Rel.Sym)
629288943Sdim        continue;
630288943Sdim
631288943Sdim      // Set the Index and the IsExtern bit.
632288943Sdim      unsigned Index = Rel.Sym->getIndex();
633288943Sdim      assert(isInt<24>(Index));
634341825Sdim      if (W.Endian == support::little)
635288943Sdim        Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);
636288943Sdim      else
637288943Sdim        Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
638288943Sdim    }
639288943Sdim  }
640224145Sdim}
641218893Sdim
642224145Sdimvoid MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm,
643224145Sdim                                               const MCAsmLayout &Layout) {
644224145Sdim  uint64_t StartAddress = 0;
645288943Sdim  for (const MCSection *Sec : Layout.getSectionOrder()) {
646309124Sdim    StartAddress = alignTo(StartAddress, Sec->getAlignment());
647288943Sdim    SectionAddress[Sec] = StartAddress;
648288943Sdim    StartAddress += Layout.getSectionAddressSize(Sec);
649208599Srdivacky
650224145Sdim    // Explicitly pad the section to match the alignment requirements of the
651224145Sdim    // following one. This is for 'gas' compatibility, it shouldn't
652224145Sdim    /// strictly be necessary.
653288943Sdim    StartAddress += getPaddingSize(Sec, Layout);
654205407Srdivacky  }
655224145Sdim}
656205407Srdivacky
657288943Sdimvoid MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
658224145Sdim                                                const MCAsmLayout &Layout) {
659224145Sdim  computeSectionAddresses(Asm, Layout);
660205407Srdivacky
661224145Sdim  // Create symbol data for any indirect symbols.
662288943Sdim  bindIndirectSymbols(Asm);
663224145Sdim}
664205407Srdivacky
665288943Sdimbool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
666296417Sdim    const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B,
667296417Sdim    bool InSet) const {
668296417Sdim  // FIXME: We don't handle things like
669296417Sdim  // foo = .
670296417Sdim  // creating atoms.
671296417Sdim  if (A.isVariable() || B.isVariable())
672296417Sdim    return false;
673296417Sdim  return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, A, B,
674296417Sdim                                                                InSet);
675296417Sdim}
676296417Sdim
677296417Sdimbool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
678288943Sdim    const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
679288943Sdim    bool InSet, bool IsPCRel) const {
680224145Sdim  if (InSet)
681224145Sdim    return true;
682218893Sdim
683224145Sdim  // The effective address is
684224145Sdim  //     addr(atom(A)) + offset(A)
685224145Sdim  //   - addr(atom(B)) - offset(B)
686224145Sdim  // and the offsets are not relocatable, so the fixup is fully resolved when
687224145Sdim  //  addr(atom(A)) - addr(atom(B)) == 0.
688288943Sdim  const MCSymbol &SA = findAliasedSymbol(SymA);
689224145Sdim  const MCSection &SecA = SA.getSection();
690288943Sdim  const MCSection &SecB = *FB.getParent();
691205407Srdivacky
692224145Sdim  if (IsPCRel) {
693224145Sdim    // The simple (Darwin, except on x86_64) way of dealing with this was to
694224145Sdim    // assume that any reference to a temporary symbol *must* be a temporary
695224145Sdim    // symbol in the same atom, unless the sections differ. Therefore, any PCrel
696224145Sdim    // relocation to a temporary symbol (in the same section) is fully
697224145Sdim    // resolved. This also works in conjunction with absolutized .set, which
698224145Sdim    // requires the compiler to use .set to absolutize the differences between
699224145Sdim    // symbols which the compiler knows to be assembly time constants, so we
700224145Sdim    // don't need to worry about considering symbol differences fully resolved.
701234353Sdim    //
702234353Sdim    // If the file isn't using sub-sections-via-symbols, we can make the
703234353Sdim    // same assumptions about any symbol that we normally make about
704234353Sdim    // assembler locals.
705205407Srdivacky
706276479Sdim    bool hasReliableSymbolDifference = isX86_64();
707276479Sdim    if (!hasReliableSymbolDifference) {
708234353Sdim      if (!SA.isInSection() || &SecA != &SecB ||
709288943Sdim          (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() &&
710234353Sdim           Asm.getSubsectionsViaSymbols()))
711224145Sdim        return false;
712224145Sdim      return true;
713205407Srdivacky    }
714226633Sdim    // For Darwin x86_64, there is one special case when the reference IsPCRel.
715226633Sdim    // If the fragment with the reference does not have a base symbol but meets
716226633Sdim    // the simple way of dealing with this, in that it is a temporary symbol in
717226633Sdim    // the same atom then it is assumed to be fully resolved.  This is needed so
718226633Sdim    // a relocation entry is not created and so the static linker does not
719226633Sdim    // mess up the reference later.
720226633Sdim    else if(!FB.getAtom() &&
721226633Sdim            SA.isTemporary() && SA.isInSection() && &SecA == &SecB){
722226633Sdim      return true;
723226633Sdim    }
724205407Srdivacky  }
725205407Srdivacky
726280031Sdim  // If they are not in the same section, we can't compute the diff.
727280031Sdim  if (&SecA != &SecB)
728280031Sdim    return false;
729280031Sdim
730288943Sdim  const MCFragment *FA = SA.getFragment();
731205407Srdivacky
732226633Sdim  // Bail if the symbol has no fragment.
733226633Sdim  if (!FA)
734226633Sdim    return false;
735226633Sdim
736224145Sdim  // If the atoms are the same, they are guaranteed to have the same address.
737288943Sdim  if (FA->getAtom() == FB.getAtom())
738224145Sdim    return true;
739205407Srdivacky
740224145Sdim  // Otherwise, we can't prove this is fully resolved.
741224145Sdim  return false;
742224145Sdim}
743205407Srdivacky
744327952Sdimstatic MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
745327952Sdim  switch (Type) {
746327952Sdim  case MCVM_OSXVersionMin:     return MachO::LC_VERSION_MIN_MACOSX;
747327952Sdim  case MCVM_IOSVersionMin:     return MachO::LC_VERSION_MIN_IPHONEOS;
748327952Sdim  case MCVM_TvOSVersionMin:    return MachO::LC_VERSION_MIN_TVOS;
749327952Sdim  case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS;
750327952Sdim  }
751327952Sdim  llvm_unreachable("Invalid mc version min type");
752327952Sdim}
753327952Sdim
754341825Sdimuint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
755341825Sdim                                       const MCAsmLayout &Layout) {
756341825Sdim  uint64_t StartOffset = W.OS.tell();
757341825Sdim
758288943Sdim  // Compute symbol table information and bind symbol indices.
759288943Sdim  computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
760288943Sdim                     UndefinedSymbolData);
761288943Sdim
762224145Sdim  unsigned NumSections = Asm.size();
763327952Sdim  const MCAssembler::VersionInfoType &VersionInfo =
764327952Sdim    Layout.getAssembler().getVersionInfo();
765205407Srdivacky
766224145Sdim  // The section data starts after the header, the segment load command (and
767224145Sdim  // section headers) and the symbol table.
768224145Sdim  unsigned NumLoadCommands = 1;
769224145Sdim  uint64_t LoadCommandsSize = is64Bit() ?
770261991Sdim    sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):
771261991Sdim    sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
772205407Srdivacky
773276479Sdim  // Add the deployment target version info load command size, if used.
774276479Sdim  if (VersionInfo.Major != 0) {
775276479Sdim    ++NumLoadCommands;
776327952Sdim    if (VersionInfo.EmitBuildVersion)
777327952Sdim      LoadCommandsSize += sizeof(MachO::build_version_command);
778327952Sdim    else
779327952Sdim      LoadCommandsSize += sizeof(MachO::version_min_command);
780276479Sdim  }
781276479Sdim
782249423Sdim  // Add the data-in-code load command size, if used.
783249423Sdim  unsigned NumDataRegions = Asm.getDataRegions().size();
784249423Sdim  if (NumDataRegions) {
785249423Sdim    ++NumLoadCommands;
786261991Sdim    LoadCommandsSize += sizeof(MachO::linkedit_data_command);
787249423Sdim  }
788249423Sdim
789276479Sdim  // Add the loh load command size, if used.
790276479Sdim  uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout);
791309124Sdim  uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4);
792276479Sdim  if (LOHSize) {
793276479Sdim    ++NumLoadCommands;
794276479Sdim    LoadCommandsSize += sizeof(MachO::linkedit_data_command);
795276479Sdim  }
796276479Sdim
797224145Sdim  // Add the symbol table load command sizes, if used.
798224145Sdim  unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
799224145Sdim    UndefinedSymbolData.size();
800224145Sdim  if (NumSymbols) {
801224145Sdim    NumLoadCommands += 2;
802261991Sdim    LoadCommandsSize += (sizeof(MachO::symtab_command) +
803261991Sdim                         sizeof(MachO::dysymtab_command));
804224145Sdim  }
805205407Srdivacky
806249423Sdim  // Add the linker option load commands sizes.
807288943Sdim  for (const auto &Option : Asm.getLinkerOptions()) {
808239462Sdim    ++NumLoadCommands;
809288943Sdim    LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(Option, is64Bit());
810239462Sdim  }
811296417Sdim
812224145Sdim  // Compute the total size of the section data, as well as its file size and vm
813224145Sdim  // size.
814261991Sdim  uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) :
815261991Sdim                               sizeof(MachO::mach_header)) + LoadCommandsSize;
816224145Sdim  uint64_t SectionDataSize = 0;
817224145Sdim  uint64_t SectionDataFileSize = 0;
818224145Sdim  uint64_t VMSize = 0;
819288943Sdim  for (const MCSection &Sec : Asm) {
820288943Sdim    uint64_t Address = getSectionAddress(&Sec);
821288943Sdim    uint64_t Size = Layout.getSectionAddressSize(&Sec);
822288943Sdim    uint64_t FileSize = Layout.getSectionFileSize(&Sec);
823288943Sdim    FileSize += getPaddingSize(&Sec, Layout);
824205407Srdivacky
825224145Sdim    VMSize = std::max(VMSize, Address + Size);
826205407Srdivacky
827288943Sdim    if (Sec.isVirtualSection())
828224145Sdim      continue;
829205407Srdivacky
830224145Sdim    SectionDataSize = std::max(SectionDataSize, Address + Size);
831224145Sdim    SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
832205407Srdivacky  }
833205407Srdivacky
834224145Sdim  // The section data is padded to 4 bytes.
835224145Sdim  //
836224145Sdim  // FIXME: Is this machine dependent?
837360784Sdim  unsigned SectionDataPadding =
838360784Sdim      offsetToAlignment(SectionDataFileSize, Align(4));
839224145Sdim  SectionDataFileSize += SectionDataPadding;
840218893Sdim
841224145Sdim  // Write the prolog, starting with the header and load command...
842296417Sdim  writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize,
843224145Sdim              Asm.getSubsectionsViaSymbols());
844296417Sdim  uint32_t Prot =
845296417Sdim      MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
846296417Sdim  writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart,
847296417Sdim                          SectionDataSize, Prot, Prot);
848218893Sdim
849224145Sdim  // ... and then the section headers.
850224145Sdim  uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
851296417Sdim  for (const MCSection &Section : Asm) {
852296417Sdim    const auto &Sec = cast<MCSectionMachO>(Section);
853288943Sdim    std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
854224145Sdim    unsigned NumRelocs = Relocs.size();
855288943Sdim    uint64_t SectionStart = SectionDataStart + getSectionAddress(&Sec);
856296417Sdim    unsigned Flags = Sec.getTypeAndAttributes();
857296417Sdim    if (Sec.hasInstructions())
858296417Sdim      Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS;
859296417Sdim    writeSection(Layout, Sec, getSectionAddress(&Sec), SectionStart, Flags,
860296417Sdim                 RelocTableEnd, NumRelocs);
861261991Sdim    RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);
862205407Srdivacky  }
863205407Srdivacky
864276479Sdim  // Write out the deployment target information, if it's available.
865276479Sdim  if (VersionInfo.Major != 0) {
866344779Sdim    auto EncodeVersion = [](VersionTuple V) -> uint32_t {
867344779Sdim      assert(!V.empty() && "empty version");
868344779Sdim      unsigned Update = V.getSubminor() ? *V.getSubminor() : 0;
869344779Sdim      unsigned Minor = V.getMinor() ? *V.getMinor() : 0;
870344779Sdim      assert(Update < 256 && "unencodable update target version");
871344779Sdim      assert(Minor < 256 && "unencodable minor target version");
872344779Sdim      assert(V.getMajor() < 65536 && "unencodable major target version");
873344779Sdim      return Update | (Minor << 8) | (V.getMajor() << 16);
874344779Sdim    };
875344779Sdim    uint32_t EncodedVersion = EncodeVersion(
876344779Sdim        VersionTuple(VersionInfo.Major, VersionInfo.Minor, VersionInfo.Update));
877344779Sdim    uint32_t SDKVersion = !VersionInfo.SDKVersion.empty()
878344779Sdim                              ? EncodeVersion(VersionInfo.SDKVersion)
879344779Sdim                              : 0;
880327952Sdim    if (VersionInfo.EmitBuildVersion) {
881327952Sdim      // FIXME: Currently empty tools. Add clang version in the future.
882341825Sdim      W.write<uint32_t>(MachO::LC_BUILD_VERSION);
883341825Sdim      W.write<uint32_t>(sizeof(MachO::build_version_command));
884341825Sdim      W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);
885341825Sdim      W.write<uint32_t>(EncodedVersion);
886344779Sdim      W.write<uint32_t>(SDKVersion);
887341825Sdim      W.write<uint32_t>(0);         // Empty tools list.
888327952Sdim    } else {
889327952Sdim      MachO::LoadCommandType LCType
890327952Sdim        = getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
891341825Sdim      W.write<uint32_t>(LCType);
892341825Sdim      W.write<uint32_t>(sizeof(MachO::version_min_command));
893341825Sdim      W.write<uint32_t>(EncodedVersion);
894344779Sdim      W.write<uint32_t>(SDKVersion);
895296417Sdim    }
896276479Sdim  }
897276479Sdim
898239462Sdim  // Write the data-in-code load command, if used.
899239462Sdim  uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
900239462Sdim  if (NumDataRegions) {
901239462Sdim    uint64_t DataRegionsOffset = RelocTableEnd;
902239462Sdim    uint64_t DataRegionsSize = NumDataRegions * 8;
903288943Sdim    writeLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset,
904239462Sdim                             DataRegionsSize);
905239462Sdim  }
906239462Sdim
907276479Sdim  // Write the loh load command, if used.
908276479Sdim  uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize;
909276479Sdim  if (LOHSize)
910288943Sdim    writeLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT,
911276479Sdim                             DataInCodeTableEnd, LOHSize);
912276479Sdim
913224145Sdim  // Write the symbol table load command, if used.
914224145Sdim  if (NumSymbols) {
915224145Sdim    unsigned FirstLocalSymbol = 0;
916224145Sdim    unsigned NumLocalSymbols = LocalSymbolData.size();
917224145Sdim    unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
918224145Sdim    unsigned NumExternalSymbols = ExternalSymbolData.size();
919224145Sdim    unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
920224145Sdim    unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
921224145Sdim    unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
922224145Sdim    unsigned NumSymTabSymbols =
923224145Sdim      NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
924224145Sdim    uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
925224145Sdim    uint64_t IndirectSymbolOffset = 0;
926218893Sdim
927224145Sdim    // If used, the indirect symbols are written after the section data.
928224145Sdim    if (NumIndirectSymbols)
929276479Sdim      IndirectSymbolOffset = LOHTableEnd;
930218893Sdim
931224145Sdim    // The symbol table is written after the indirect symbol data.
932276479Sdim    uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize;
933218893Sdim
934224145Sdim    // The string table is written after symbol table.
935224145Sdim    uint64_t StringTableOffset =
936261991Sdim      SymbolTableOffset + NumSymTabSymbols * (is64Bit() ?
937261991Sdim                                              sizeof(MachO::nlist_64) :
938261991Sdim                                              sizeof(MachO::nlist));
939288943Sdim    writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
940314564Sdim                           StringTableOffset, StringTable.getSize());
941218893Sdim
942288943Sdim    writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
943224145Sdim                             FirstExternalSymbol, NumExternalSymbols,
944224145Sdim                             FirstUndefinedSymbol, NumUndefinedSymbols,
945224145Sdim                             IndirectSymbolOffset, NumIndirectSymbols);
946224145Sdim  }
947218893Sdim
948249423Sdim  // Write the linker options load commands.
949288943Sdim  for (const auto &Option : Asm.getLinkerOptions())
950288943Sdim    writeLinkerOptionsLoadCommand(Option);
951249423Sdim
952224145Sdim  // Write the actual section data.
953288943Sdim  for (const MCSection &Sec : Asm) {
954341825Sdim    Asm.writeSectionData(W.OS, &Sec, Layout);
955218893Sdim
956288943Sdim    uint64_t Pad = getPaddingSize(&Sec, Layout);
957341825Sdim    W.OS.write_zeros(Pad);
958218893Sdim  }
959218893Sdim
960224145Sdim  // Write the extra padding.
961341825Sdim  W.OS.write_zeros(SectionDataPadding);
962205407Srdivacky
963224145Sdim  // Write the relocation entries.
964288943Sdim  for (const MCSection &Sec : Asm) {
965224145Sdim    // Write the section relocation entries, in reverse order to match 'as'
966224145Sdim    // (approximately, the exact algorithm is more complicated than this).
967288943Sdim    std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
968288943Sdim    for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) {
969341825Sdim      W.write<uint32_t>(Rel.MRE.r_word0);
970341825Sdim      W.write<uint32_t>(Rel.MRE.r_word1);
971205407Srdivacky    }
972224145Sdim  }
973205407Srdivacky
974239462Sdim  // Write out the data-in-code region payload, if there is one.
975239462Sdim  for (MCAssembler::const_data_region_iterator
976239462Sdim         it = Asm.data_region_begin(), ie = Asm.data_region_end();
977239462Sdim         it != ie; ++it) {
978239462Sdim    const DataRegionData *Data = &(*it);
979288943Sdim    uint64_t Start = getSymbolAddress(*Data->Start, Layout);
980341825Sdim    uint64_t End;
981341825Sdim    if (Data->End)
982341825Sdim      End = getSymbolAddress(*Data->End, Layout);
983341825Sdim    else
984341825Sdim      report_fatal_error("Data region not terminated");
985341825Sdim
986341825Sdim    LLVM_DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
987341825Sdim                      << "  start: " << Start << "(" << Data->Start->getName()
988341825Sdim                      << ")"
989341825Sdim                      << "  end: " << End << "(" << Data->End->getName() << ")"
990341825Sdim                      << "  size: " << End - Start << "\n");
991341825Sdim    W.write<uint32_t>(Start);
992341825Sdim    W.write<uint16_t>(End - Start);
993341825Sdim    W.write<uint16_t>(Data->Kind);
994239462Sdim  }
995239462Sdim
996276479Sdim  // Write out the loh commands, if there is one.
997276479Sdim  if (LOHSize) {
998276479Sdim#ifndef NDEBUG
999341825Sdim    unsigned Start = W.OS.tell();
1000276479Sdim#endif
1001288943Sdim    Asm.getLOHContainer().emit(*this, Layout);
1002276479Sdim    // Pad to a multiple of the pointer size.
1003360784Sdim    W.OS.write_zeros(
1004360784Sdim        offsetToAlignment(LOHRawSize, is64Bit() ? Align(8) : Align(4)));
1005341825Sdim    assert(W.OS.tell() - Start == LOHSize);
1006276479Sdim  }
1007276479Sdim
1008224145Sdim  // Write the symbol table data, if used.
1009224145Sdim  if (NumSymbols) {
1010224145Sdim    // Write the indirect symbol entries.
1011224145Sdim    for (MCAssembler::const_indirect_symbol_iterator
1012224145Sdim           it = Asm.indirect_symbol_begin(),
1013224145Sdim           ie = Asm.indirect_symbol_end(); it != ie; ++it) {
1014276479Sdim      // Indirect symbols in the non-lazy symbol pointer section have some
1015224145Sdim      // special handling.
1016224145Sdim      const MCSectionMachO &Section =
1017288943Sdim          static_cast<const MCSectionMachO &>(*it->Section);
1018276479Sdim      if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) {
1019224145Sdim        // If this symbol is defined and internal, mark it as such.
1020288943Sdim        if (it->Symbol->isDefined() && !it->Symbol->isExternal()) {
1021261991Sdim          uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
1022224145Sdim          if (it->Symbol->isAbsolute())
1023261991Sdim            Flags |= MachO::INDIRECT_SYMBOL_ABS;
1024341825Sdim          W.write<uint32_t>(Flags);
1025224145Sdim          continue;
1026224145Sdim        }
1027224145Sdim      }
1028205407Srdivacky
1029341825Sdim      W.write<uint32_t>(it->Symbol->getIndex());
1030205407Srdivacky    }
1031205407Srdivacky
1032224145Sdim    // FIXME: Check that offsets match computed ones.
1033205407Srdivacky
1034224145Sdim    // Write the symbol table entries.
1035288943Sdim    for (auto *SymbolData :
1036288943Sdim         {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
1037288943Sdim      for (MachSymbolData &Entry : *SymbolData)
1038288943Sdim        writeNlist(Entry, Layout);
1039205407Srdivacky
1040224145Sdim    // Write the string table.
1041341825Sdim    StringTable.write(W.OS);
1042205407Srdivacky  }
1043341825Sdim
1044341825Sdim  return W.OS.tell() - StartOffset;
1045205407Srdivacky}
1046205407Srdivacky
1047327952Sdimstd::unique_ptr<MCObjectWriter>
1048327952Sdimllvm::createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
1049327952Sdim                             raw_pwrite_stream &OS, bool IsLittleEndian) {
1050360784Sdim  return std::make_unique<MachObjectWriter>(std::move(MOTW), OS,
1051327952Sdim                                             IsLittleEndian);
1052205407Srdivacky}
1053