xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MachObjectWriter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
100b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
110b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
120b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
14*0fca6ea1SDimitry Andric #include "llvm/MC/MCAsmInfoDarwin.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCFragment.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCMachObjectWriter.h"
2281ad6265SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCSection.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCSectionMachO.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCSymbolMachO.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
298bcb0991SDimitry Andric #include "llvm/Support/Alignment.h"
300b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
310b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
3381ad6265SDimitry Andric #include "llvm/Support/LEB128.h"
340b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
350b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
360b57cec5SDimitry Andric #include <algorithm>
370b57cec5SDimitry Andric #include <cassert>
380b57cec5SDimitry Andric #include <cstdint>
390b57cec5SDimitry Andric #include <string>
400b57cec5SDimitry Andric #include <utility>
410b57cec5SDimitry Andric #include <vector>
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric using namespace llvm;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric #define DEBUG_TYPE "mc"
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric void MachObjectWriter::reset() {
480b57cec5SDimitry Andric   Relocations.clear();
490b57cec5SDimitry Andric   IndirectSymBase.clear();
50*0fca6ea1SDimitry Andric   IndirectSymbols.clear();
51*0fca6ea1SDimitry Andric   DataRegions.clear();
52*0fca6ea1SDimitry Andric   SectionAddress.clear();
53*0fca6ea1SDimitry Andric   SectionOrder.clear();
540b57cec5SDimitry Andric   StringTable.clear();
550b57cec5SDimitry Andric   LocalSymbolData.clear();
560b57cec5SDimitry Andric   ExternalSymbolData.clear();
570b57cec5SDimitry Andric   UndefinedSymbolData.clear();
58*0fca6ea1SDimitry Andric   LOHContainer.reset();
59*0fca6ea1SDimitry Andric   VersionInfo.Major = 0;
60*0fca6ea1SDimitry Andric   VersionInfo.SDKVersion = VersionTuple();
61*0fca6ea1SDimitry Andric   TargetVariantVersionInfo.Major = 0;
62*0fca6ea1SDimitry Andric   TargetVariantVersionInfo.SDKVersion = VersionTuple();
63*0fca6ea1SDimitry Andric   LinkerOptions.clear();
640b57cec5SDimitry Andric   MCObjectWriter::reset();
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) {
680b57cec5SDimitry Andric   // Undefined symbols are always extern.
690b57cec5SDimitry Andric   if (S.isUndefined())
700b57cec5SDimitry Andric     return true;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   // References to weak definitions require external relocation entries; the
730b57cec5SDimitry Andric   // definition may not always be the one in the same object file.
740b57cec5SDimitry Andric   if (cast<MCSymbolMachO>(S).isWeakDefinition())
750b57cec5SDimitry Andric     return true;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   // Otherwise, we can use an internal relocation.
780b57cec5SDimitry Andric   return false;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric bool MachObjectWriter::
820b57cec5SDimitry Andric MachSymbolData::operator<(const MachSymbolData &RHS) const {
830b57cec5SDimitry Andric   return Symbol->getName() < RHS.Symbol->getName();
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric bool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
870b57cec5SDimitry Andric   const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo(
880b57cec5SDimitry Andric     (MCFixupKind) Kind);
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
93*0fca6ea1SDimitry Andric uint64_t
94*0fca6ea1SDimitry Andric MachObjectWriter::getFragmentAddress(const MCAssembler &Asm,
95*0fca6ea1SDimitry Andric                                      const MCFragment *Fragment) const {
960b57cec5SDimitry Andric   return getSectionAddress(Fragment->getParent()) +
97*0fca6ea1SDimitry Andric          Asm.getFragmentOffset(*Fragment);
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S,
101*0fca6ea1SDimitry Andric                                             const MCAssembler &Asm) const {
1020b57cec5SDimitry Andric   // If this is a variable, then recursively evaluate now.
1030b57cec5SDimitry Andric   if (S.isVariable()) {
1040b57cec5SDimitry Andric     if (const MCConstantExpr *C =
1050b57cec5SDimitry Andric           dyn_cast<const MCConstantExpr>(S.getVariableValue()))
1060b57cec5SDimitry Andric       return C->getValue();
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric     MCValue Target;
109*0fca6ea1SDimitry Andric     if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Asm, nullptr))
1100b57cec5SDimitry Andric       report_fatal_error("unable to evaluate offset for variable '" +
1110b57cec5SDimitry Andric                          S.getName() + "'");
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     // Verify that any used symbols are defined.
1140b57cec5SDimitry Andric     if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined())
1150b57cec5SDimitry Andric       report_fatal_error("unable to evaluate offset to undefined symbol '" +
1160b57cec5SDimitry Andric                          Target.getSymA()->getSymbol().getName() + "'");
1170b57cec5SDimitry Andric     if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined())
1180b57cec5SDimitry Andric       report_fatal_error("unable to evaluate offset to undefined symbol '" +
1190b57cec5SDimitry Andric                          Target.getSymB()->getSymbol().getName() + "'");
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     uint64_t Address = Target.getConstant();
1220b57cec5SDimitry Andric     if (Target.getSymA())
123*0fca6ea1SDimitry Andric       Address += getSymbolAddress(Target.getSymA()->getSymbol(), Asm);
1240b57cec5SDimitry Andric     if (Target.getSymB())
125*0fca6ea1SDimitry Andric       Address += getSymbolAddress(Target.getSymB()->getSymbol(), Asm);
1260b57cec5SDimitry Andric     return Address;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   return getSectionAddress(S.getFragment()->getParent()) +
130*0fca6ea1SDimitry Andric          Asm.getSymbolOffset(S);
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
133*0fca6ea1SDimitry Andric uint64_t MachObjectWriter::getPaddingSize(const MCAssembler &Asm,
134*0fca6ea1SDimitry Andric                                           const MCSection *Sec) const {
135*0fca6ea1SDimitry Andric   uint64_t EndAddr = getSectionAddress(Sec) + Asm.getSectionAddressSize(*Sec);
136*0fca6ea1SDimitry Andric   unsigned Next = cast<MCSectionMachO>(Sec)->getLayoutOrder() + 1;
137*0fca6ea1SDimitry Andric   if (Next >= SectionOrder.size())
1380b57cec5SDimitry Andric     return 0;
1390b57cec5SDimitry Andric 
140*0fca6ea1SDimitry Andric   const MCSection &NextSec = *SectionOrder[Next];
1410b57cec5SDimitry Andric   if (NextSec.isVirtualSection())
1420b57cec5SDimitry Andric     return 0;
143bdd1243dSDimitry Andric   return offsetToAlignment(EndAddr, NextSec.getAlign());
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
146*0fca6ea1SDimitry Andric static bool isSymbolLinkerVisible(const MCSymbol &Symbol) {
147*0fca6ea1SDimitry Andric   // Non-temporary labels should always be visible to the linker.
148*0fca6ea1SDimitry Andric   if (!Symbol.isTemporary())
149*0fca6ea1SDimitry Andric     return true;
150*0fca6ea1SDimitry Andric 
151*0fca6ea1SDimitry Andric   if (Symbol.isUsedInReloc())
152*0fca6ea1SDimitry Andric     return true;
153*0fca6ea1SDimitry Andric 
154*0fca6ea1SDimitry Andric   return false;
155*0fca6ea1SDimitry Andric }
156*0fca6ea1SDimitry Andric 
157*0fca6ea1SDimitry Andric const MCSymbol *MachObjectWriter::getAtom(const MCSymbol &S) const {
158*0fca6ea1SDimitry Andric   // Linker visible symbols define atoms.
159*0fca6ea1SDimitry Andric   if (isSymbolLinkerVisible(S))
160*0fca6ea1SDimitry Andric     return &S;
161*0fca6ea1SDimitry Andric 
162*0fca6ea1SDimitry Andric   // Absolute and undefined symbols have no defining atom.
163*0fca6ea1SDimitry Andric   if (!S.isInSection())
164*0fca6ea1SDimitry Andric     return nullptr;
165*0fca6ea1SDimitry Andric 
166*0fca6ea1SDimitry Andric   // Non-linker visible symbols in sections which can't be atomized have no
167*0fca6ea1SDimitry Andric   // defining atom.
168*0fca6ea1SDimitry Andric   if (!MCAsmInfoDarwin::isSectionAtomizableBySymbols(
169*0fca6ea1SDimitry Andric           *S.getFragment()->getParent()))
170*0fca6ea1SDimitry Andric     return nullptr;
171*0fca6ea1SDimitry Andric 
172*0fca6ea1SDimitry Andric   // Otherwise, return the atom for the containing fragment.
173*0fca6ea1SDimitry Andric   return S.getFragment()->getAtom();
174*0fca6ea1SDimitry Andric }
175*0fca6ea1SDimitry Andric 
1760b57cec5SDimitry Andric void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
1770b57cec5SDimitry Andric                                    unsigned NumLoadCommands,
1780b57cec5SDimitry Andric                                    unsigned LoadCommandsSize,
1790b57cec5SDimitry Andric                                    bool SubsectionsViaSymbols) {
1800b57cec5SDimitry Andric   uint32_t Flags = 0;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   if (SubsectionsViaSymbols)
1830b57cec5SDimitry Andric     Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   // struct mach_header (28 bytes) or
1860b57cec5SDimitry Andric   // struct mach_header_64 (32 bytes)
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   uint64_t Start = W.OS.tell();
1890b57cec5SDimitry Andric   (void) Start;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   W.write<uint32_t>(TargetObjectWriter->getCPUType());
1940b57cec5SDimitry Andric   W.write<uint32_t>(TargetObjectWriter->getCPUSubtype());
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   W.write<uint32_t>(Type);
1970b57cec5SDimitry Andric   W.write<uint32_t>(NumLoadCommands);
1980b57cec5SDimitry Andric   W.write<uint32_t>(LoadCommandsSize);
1990b57cec5SDimitry Andric   W.write<uint32_t>(Flags);
2000b57cec5SDimitry Andric   if (is64Bit())
2010b57cec5SDimitry Andric     W.write<uint32_t>(0); // reserved
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64)
2040b57cec5SDimitry Andric                                            : sizeof(MachO::mach_header)));
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric void MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) {
2080b57cec5SDimitry Andric   assert(Size >= Str.size());
2090b57cec5SDimitry Andric   W.OS << Str;
2100b57cec5SDimitry Andric   W.OS.write_zeros(Size - Str.size());
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric /// writeSegmentLoadCommand - Write a segment load command.
2140b57cec5SDimitry Andric ///
2150b57cec5SDimitry Andric /// \param NumSections The number of sections in this segment.
2160b57cec5SDimitry Andric /// \param SectionDataSize The total size of the sections.
2170b57cec5SDimitry Andric void MachObjectWriter::writeSegmentLoadCommand(
2180b57cec5SDimitry Andric     StringRef Name, unsigned NumSections, uint64_t VMAddr, uint64_t VMSize,
2190b57cec5SDimitry Andric     uint64_t SectionDataStartOffset, uint64_t SectionDataSize, uint32_t MaxProt,
2200b57cec5SDimitry Andric     uint32_t InitProt) {
2210b57cec5SDimitry Andric   // struct segment_command (56 bytes) or
2220b57cec5SDimitry Andric   // struct segment_command_64 (72 bytes)
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   uint64_t Start = W.OS.tell();
2250b57cec5SDimitry Andric   (void) Start;
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   unsigned SegmentLoadCommandSize =
2280b57cec5SDimitry Andric     is64Bit() ? sizeof(MachO::segment_command_64):
2290b57cec5SDimitry Andric     sizeof(MachO::segment_command);
2300b57cec5SDimitry Andric   W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
2310b57cec5SDimitry Andric   W.write<uint32_t>(SegmentLoadCommandSize +
2320b57cec5SDimitry Andric           NumSections * (is64Bit() ? sizeof(MachO::section_64) :
2330b57cec5SDimitry Andric                          sizeof(MachO::section)));
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   writeWithPadding(Name, 16);
2360b57cec5SDimitry Andric   if (is64Bit()) {
2370b57cec5SDimitry Andric     W.write<uint64_t>(VMAddr);                 // vmaddr
2380b57cec5SDimitry Andric     W.write<uint64_t>(VMSize); // vmsize
2390b57cec5SDimitry Andric     W.write<uint64_t>(SectionDataStartOffset); // file offset
2400b57cec5SDimitry Andric     W.write<uint64_t>(SectionDataSize); // file size
2410b57cec5SDimitry Andric   } else {
2420b57cec5SDimitry Andric     W.write<uint32_t>(VMAddr);                 // vmaddr
2430b57cec5SDimitry Andric     W.write<uint32_t>(VMSize); // vmsize
2440b57cec5SDimitry Andric     W.write<uint32_t>(SectionDataStartOffset); // file offset
2450b57cec5SDimitry Andric     W.write<uint32_t>(SectionDataSize); // file size
2460b57cec5SDimitry Andric   }
2470b57cec5SDimitry Andric   // maxprot
2480b57cec5SDimitry Andric   W.write<uint32_t>(MaxProt);
2490b57cec5SDimitry Andric   // initprot
2500b57cec5SDimitry Andric   W.write<uint32_t>(InitProt);
2510b57cec5SDimitry Andric   W.write<uint32_t>(NumSections);
2520b57cec5SDimitry Andric   W.write<uint32_t>(0); // flags
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   assert(W.OS.tell() - Start == SegmentLoadCommandSize);
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
257*0fca6ea1SDimitry Andric void MachObjectWriter::writeSection(const MCAssembler &Asm,
2580b57cec5SDimitry Andric                                     const MCSection &Sec, uint64_t VMAddr,
2590b57cec5SDimitry Andric                                     uint64_t FileOffset, unsigned Flags,
2600b57cec5SDimitry Andric                                     uint64_t RelocationsStart,
2610b57cec5SDimitry Andric                                     unsigned NumRelocations) {
262*0fca6ea1SDimitry Andric   uint64_t SectionSize = Asm.getSectionAddressSize(Sec);
2630b57cec5SDimitry Andric   const MCSectionMachO &Section = cast<MCSectionMachO>(Sec);
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   // The offset is unused for virtual sections.
2660b57cec5SDimitry Andric   if (Section.isVirtualSection()) {
267*0fca6ea1SDimitry Andric     assert(Asm.getSectionFileSize(Sec) == 0 && "Invalid file size!");
2680b57cec5SDimitry Andric     FileOffset = 0;
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   // struct section (68 bytes) or
2720b57cec5SDimitry Andric   // struct section_64 (80 bytes)
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   uint64_t Start = W.OS.tell();
2750b57cec5SDimitry Andric   (void) Start;
2760b57cec5SDimitry Andric 
2775ffd83dbSDimitry Andric   writeWithPadding(Section.getName(), 16);
2780b57cec5SDimitry Andric   writeWithPadding(Section.getSegmentName(), 16);
2790b57cec5SDimitry Andric   if (is64Bit()) {
2800b57cec5SDimitry Andric     W.write<uint64_t>(VMAddr);      // address
2810b57cec5SDimitry Andric     W.write<uint64_t>(SectionSize); // size
2820b57cec5SDimitry Andric   } else {
2830b57cec5SDimitry Andric     W.write<uint32_t>(VMAddr);      // address
2840b57cec5SDimitry Andric     W.write<uint32_t>(SectionSize); // size
2850b57cec5SDimitry Andric   }
286*0fca6ea1SDimitry Andric   assert(isUInt<32>(FileOffset) && "Cannot encode offset of section");
2870b57cec5SDimitry Andric   W.write<uint32_t>(FileOffset);
2880b57cec5SDimitry Andric 
289bdd1243dSDimitry Andric   W.write<uint32_t>(Log2(Section.getAlign()));
290*0fca6ea1SDimitry Andric   assert((!NumRelocations || isUInt<32>(RelocationsStart)) &&
291*0fca6ea1SDimitry Andric          "Cannot encode offset of relocations");
2920b57cec5SDimitry Andric   W.write<uint32_t>(NumRelocations ? RelocationsStart : 0);
2930b57cec5SDimitry Andric   W.write<uint32_t>(NumRelocations);
2940b57cec5SDimitry Andric   W.write<uint32_t>(Flags);
2950b57cec5SDimitry Andric   W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1
2960b57cec5SDimitry Andric   W.write<uint32_t>(Section.getStubSize()); // reserved2
2970b57cec5SDimitry Andric   if (is64Bit())
2980b57cec5SDimitry Andric     W.write<uint32_t>(0); // reserved3
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   assert(W.OS.tell() - Start ==
3010b57cec5SDimitry Andric          (is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,
3050b57cec5SDimitry Andric                                               uint32_t NumSymbols,
3060b57cec5SDimitry Andric                                               uint32_t StringTableOffset,
3070b57cec5SDimitry Andric                                               uint32_t StringTableSize) {
3080b57cec5SDimitry Andric   // struct symtab_command (24 bytes)
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   uint64_t Start = W.OS.tell();
3110b57cec5SDimitry Andric   (void) Start;
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   W.write<uint32_t>(MachO::LC_SYMTAB);
3140b57cec5SDimitry Andric   W.write<uint32_t>(sizeof(MachO::symtab_command));
3150b57cec5SDimitry Andric   W.write<uint32_t>(SymbolOffset);
3160b57cec5SDimitry Andric   W.write<uint32_t>(NumSymbols);
3170b57cec5SDimitry Andric   W.write<uint32_t>(StringTableOffset);
3180b57cec5SDimitry Andric   W.write<uint32_t>(StringTableSize);
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   assert(W.OS.tell() - Start == sizeof(MachO::symtab_command));
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
3240b57cec5SDimitry Andric                                                 uint32_t NumLocalSymbols,
3250b57cec5SDimitry Andric                                                 uint32_t FirstExternalSymbol,
3260b57cec5SDimitry Andric                                                 uint32_t NumExternalSymbols,
3270b57cec5SDimitry Andric                                                 uint32_t FirstUndefinedSymbol,
3280b57cec5SDimitry Andric                                                 uint32_t NumUndefinedSymbols,
3290b57cec5SDimitry Andric                                                 uint32_t IndirectSymbolOffset,
3300b57cec5SDimitry Andric                                                 uint32_t NumIndirectSymbols) {
3310b57cec5SDimitry Andric   // struct dysymtab_command (80 bytes)
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   uint64_t Start = W.OS.tell();
3340b57cec5SDimitry Andric   (void) Start;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   W.write<uint32_t>(MachO::LC_DYSYMTAB);
3370b57cec5SDimitry Andric   W.write<uint32_t>(sizeof(MachO::dysymtab_command));
3380b57cec5SDimitry Andric   W.write<uint32_t>(FirstLocalSymbol);
3390b57cec5SDimitry Andric   W.write<uint32_t>(NumLocalSymbols);
3400b57cec5SDimitry Andric   W.write<uint32_t>(FirstExternalSymbol);
3410b57cec5SDimitry Andric   W.write<uint32_t>(NumExternalSymbols);
3420b57cec5SDimitry Andric   W.write<uint32_t>(FirstUndefinedSymbol);
3430b57cec5SDimitry Andric   W.write<uint32_t>(NumUndefinedSymbols);
3440b57cec5SDimitry Andric   W.write<uint32_t>(0); // tocoff
3450b57cec5SDimitry Andric   W.write<uint32_t>(0); // ntoc
3460b57cec5SDimitry Andric   W.write<uint32_t>(0); // modtaboff
3470b57cec5SDimitry Andric   W.write<uint32_t>(0); // nmodtab
3480b57cec5SDimitry Andric   W.write<uint32_t>(0); // extrefsymoff
3490b57cec5SDimitry Andric   W.write<uint32_t>(0); // nextrefsyms
3500b57cec5SDimitry Andric   W.write<uint32_t>(IndirectSymbolOffset);
3510b57cec5SDimitry Andric   W.write<uint32_t>(NumIndirectSymbols);
3520b57cec5SDimitry Andric   W.write<uint32_t>(0); // extreloff
3530b57cec5SDimitry Andric   W.write<uint32_t>(0); // nextrel
3540b57cec5SDimitry Andric   W.write<uint32_t>(0); // locreloff
3550b57cec5SDimitry Andric   W.write<uint32_t>(0); // nlocrel
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command));
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric MachObjectWriter::MachSymbolData *
3610b57cec5SDimitry Andric MachObjectWriter::findSymbolData(const MCSymbol &Sym) {
3620b57cec5SDimitry Andric   for (auto *SymbolData :
3630b57cec5SDimitry Andric        {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
3640b57cec5SDimitry Andric     for (MachSymbolData &Entry : *SymbolData)
3650b57cec5SDimitry Andric       if (Entry.Symbol == &Sym)
3660b57cec5SDimitry Andric         return &Entry;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   return nullptr;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric const MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const {
3720b57cec5SDimitry Andric   const MCSymbol *S = &Sym;
3730b57cec5SDimitry Andric   while (S->isVariable()) {
3740b57cec5SDimitry Andric     const MCExpr *Value = S->getVariableValue();
3750b57cec5SDimitry Andric     const auto *Ref = dyn_cast<MCSymbolRefExpr>(Value);
3760b57cec5SDimitry Andric     if (!Ref)
3770b57cec5SDimitry Andric       return *S;
3780b57cec5SDimitry Andric     S = &Ref->getSymbol();
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric   return *S;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
383*0fca6ea1SDimitry Andric void MachObjectWriter::writeNlist(MachSymbolData &MSD, const MCAssembler &Asm) {
3840b57cec5SDimitry Andric   const MCSymbol *Symbol = MSD.Symbol;
385*0fca6ea1SDimitry Andric   const auto &Data = cast<MCSymbolMachO>(*Symbol);
3860b57cec5SDimitry Andric   const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol);
3870b57cec5SDimitry Andric   uint8_t SectionIndex = MSD.SectionIndex;
3880b57cec5SDimitry Andric   uint8_t Type = 0;
3890b57cec5SDimitry Andric   uint64_t Address = 0;
3900b57cec5SDimitry Andric   bool IsAlias = Symbol != AliasedSymbol;
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   const MCSymbol &OrigSymbol = *Symbol;
3930b57cec5SDimitry Andric   MachSymbolData *AliaseeInfo;
3940b57cec5SDimitry Andric   if (IsAlias) {
3950b57cec5SDimitry Andric     AliaseeInfo = findSymbolData(*AliasedSymbol);
3960b57cec5SDimitry Andric     if (AliaseeInfo)
3970b57cec5SDimitry Andric       SectionIndex = AliaseeInfo->SectionIndex;
3980b57cec5SDimitry Andric     Symbol = AliasedSymbol;
3990b57cec5SDimitry Andric     // FIXME: Should this update Data as well?
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric   // Set the N_TYPE bits. See <mach-o/nlist.h>.
4030b57cec5SDimitry Andric   //
4040b57cec5SDimitry Andric   // FIXME: Are the prebound or indirect fields possible here?
4050b57cec5SDimitry Andric   if (IsAlias && Symbol->isUndefined())
4060b57cec5SDimitry Andric     Type = MachO::N_INDR;
4070b57cec5SDimitry Andric   else if (Symbol->isUndefined())
4080b57cec5SDimitry Andric     Type = MachO::N_UNDF;
4090b57cec5SDimitry Andric   else if (Symbol->isAbsolute())
4100b57cec5SDimitry Andric     Type = MachO::N_ABS;
4110b57cec5SDimitry Andric   else
4120b57cec5SDimitry Andric     Type = MachO::N_SECT;
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   // FIXME: Set STAB bits.
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   if (Data.isPrivateExtern())
4170b57cec5SDimitry Andric     Type |= MachO::N_PEXT;
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   // Set external bit.
4200b57cec5SDimitry Andric   if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))
4210b57cec5SDimitry Andric     Type |= MachO::N_EXT;
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   // Compute the symbol address.
4240b57cec5SDimitry Andric   if (IsAlias && Symbol->isUndefined())
4250b57cec5SDimitry Andric     Address = AliaseeInfo->StringIndex;
4260b57cec5SDimitry Andric   else if (Symbol->isDefined())
427*0fca6ea1SDimitry Andric     Address = getSymbolAddress(OrigSymbol, Asm);
4280b57cec5SDimitry Andric   else if (Symbol->isCommon()) {
4290b57cec5SDimitry Andric     // Common symbols are encoded with the size in the address
4300b57cec5SDimitry Andric     // field, and their alignment in the flags.
4310b57cec5SDimitry Andric     Address = Symbol->getCommonSize();
4320b57cec5SDimitry Andric   }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   // struct nlist (12 bytes)
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   W.write<uint32_t>(MSD.StringIndex);
4370b57cec5SDimitry Andric   W.OS << char(Type);
4380b57cec5SDimitry Andric   W.OS << char(SectionIndex);
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
4410b57cec5SDimitry Andric   // value.
4420b57cec5SDimitry Andric   bool EncodeAsAltEntry =
4430b57cec5SDimitry Andric     IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
4440b57cec5SDimitry Andric   W.write<uint16_t>(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
4450b57cec5SDimitry Andric   if (is64Bit())
4460b57cec5SDimitry Andric     W.write<uint64_t>(Address);
4470b57cec5SDimitry Andric   else
4480b57cec5SDimitry Andric     W.write<uint32_t>(Address);
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
4520b57cec5SDimitry Andric                                                 uint32_t DataOffset,
4530b57cec5SDimitry Andric                                                 uint32_t DataSize) {
4540b57cec5SDimitry Andric   uint64_t Start = W.OS.tell();
4550b57cec5SDimitry Andric   (void) Start;
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   W.write<uint32_t>(Type);
4580b57cec5SDimitry Andric   W.write<uint32_t>(sizeof(MachO::linkedit_data_command));
4590b57cec5SDimitry Andric   W.write<uint32_t>(DataOffset);
4600b57cec5SDimitry Andric   W.write<uint32_t>(DataSize);
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command));
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric static unsigned ComputeLinkerOptionsLoadCommandSize(
4660b57cec5SDimitry Andric   const std::vector<std::string> &Options, bool is64Bit)
4670b57cec5SDimitry Andric {
4680b57cec5SDimitry Andric   unsigned Size = sizeof(MachO::linker_option_command);
4690b57cec5SDimitry Andric   for (const std::string &Option : Options)
4700b57cec5SDimitry Andric     Size += Option.size() + 1;
4710b57cec5SDimitry Andric   return alignTo(Size, is64Bit ? 8 : 4);
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric void MachObjectWriter::writeLinkerOptionsLoadCommand(
4750b57cec5SDimitry Andric   const std::vector<std::string> &Options)
4760b57cec5SDimitry Andric {
4770b57cec5SDimitry Andric   unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());
4780b57cec5SDimitry Andric   uint64_t Start = W.OS.tell();
4790b57cec5SDimitry Andric   (void) Start;
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric   W.write<uint32_t>(MachO::LC_LINKER_OPTION);
4820b57cec5SDimitry Andric   W.write<uint32_t>(Size);
4830b57cec5SDimitry Andric   W.write<uint32_t>(Options.size());
4840b57cec5SDimitry Andric   uint64_t BytesWritten = sizeof(MachO::linker_option_command);
4850b57cec5SDimitry Andric   for (const std::string &Option : Options) {
4860b57cec5SDimitry Andric     // Write each string, including the null byte.
4870b57cec5SDimitry Andric     W.OS << Option << '\0';
4880b57cec5SDimitry Andric     BytesWritten += Option.size() + 1;
4890b57cec5SDimitry Andric   }
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   // Pad to a multiple of the pointer size.
4928bcb0991SDimitry Andric   W.OS.write_zeros(
4938bcb0991SDimitry Andric       offsetToAlignment(BytesWritten, is64Bit() ? Align(8) : Align(4)));
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   assert(W.OS.tell() - Start == Size);
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric static bool isFixupTargetValid(const MCValue &Target) {
4990b57cec5SDimitry Andric   // Target is (LHS - RHS + cst).
5000b57cec5SDimitry Andric   // We don't support the form where LHS is null: -RHS + cst
5010b57cec5SDimitry Andric   if (!Target.getSymA() && Target.getSymB())
5020b57cec5SDimitry Andric     return false;
5030b57cec5SDimitry Andric   return true;
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric void MachObjectWriter::recordRelocation(MCAssembler &Asm,
5070b57cec5SDimitry Andric                                         const MCFragment *Fragment,
5080b57cec5SDimitry Andric                                         const MCFixup &Fixup, MCValue Target,
5090b57cec5SDimitry Andric                                         uint64_t &FixedValue) {
5100b57cec5SDimitry Andric   if (!isFixupTargetValid(Target)) {
5110b57cec5SDimitry Andric     Asm.getContext().reportError(Fixup.getLoc(),
5120b57cec5SDimitry Andric                                  "unsupported relocation expression");
5130b57cec5SDimitry Andric     return;
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric 
516*0fca6ea1SDimitry Andric   TargetObjectWriter->recordRelocation(this, Asm, Fragment, Fixup, Target,
517*0fca6ea1SDimitry Andric                                        FixedValue);
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) {
5210b57cec5SDimitry Andric   // This is the point where 'as' creates actual symbols for indirect symbols
5220b57cec5SDimitry Andric   // (in the following two passes). It would be easier for us to do this sooner
5230b57cec5SDimitry Andric   // when we see the attribute, but that makes getting the order in the symbol
5240b57cec5SDimitry Andric   // table much more complicated than it is worth.
5250b57cec5SDimitry Andric   //
5260b57cec5SDimitry Andric   // FIXME: Revisit this when the dust settles.
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   // Report errors for use of .indirect_symbol not in a symbol pointer section
5290b57cec5SDimitry Andric   // or stub section.
530*0fca6ea1SDimitry Andric   for (IndirectSymbolData &ISD : IndirectSymbols) {
5310eae32dcSDimitry Andric     const MCSectionMachO &Section = cast<MCSectionMachO>(*ISD.Section);
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric     if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
5340b57cec5SDimitry Andric         Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
5350b57cec5SDimitry Andric         Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
5360b57cec5SDimitry Andric         Section.getType() != MachO::S_SYMBOL_STUBS) {
5370eae32dcSDimitry Andric       MCSymbol &Symbol = *ISD.Symbol;
5380b57cec5SDimitry Andric       report_fatal_error("indirect symbol '" + Symbol.getName() +
5390b57cec5SDimitry Andric                          "' not in a symbol pointer or stub section");
5400b57cec5SDimitry Andric     }
5410b57cec5SDimitry Andric   }
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   // Bind non-lazy symbol pointers first.
544*0fca6ea1SDimitry Andric   for (auto [IndirectIndex, ISD] : enumerate(IndirectSymbols)) {
545*0fca6ea1SDimitry Andric     const auto &Section = cast<MCSectionMachO>(*ISD.Section);
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric     if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
5480b57cec5SDimitry Andric         Section.getType() !=  MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
5490b57cec5SDimitry Andric       continue;
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric     // Initialize the section indirect symbol base, if necessary.
552*0fca6ea1SDimitry Andric     IndirectSymBase.insert(std::make_pair(ISD.Section, IndirectIndex));
5530b57cec5SDimitry Andric 
554*0fca6ea1SDimitry Andric     Asm.registerSymbol(*ISD.Symbol);
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   // Then lazy symbol pointers and symbol stubs.
558*0fca6ea1SDimitry Andric   for (auto [IndirectIndex, ISD] : enumerate(IndirectSymbols)) {
559*0fca6ea1SDimitry Andric     const auto &Section = cast<MCSectionMachO>(*ISD.Section);
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric     if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
5620b57cec5SDimitry Andric         Section.getType() != MachO::S_SYMBOL_STUBS)
5630b57cec5SDimitry Andric       continue;
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric     // Initialize the section indirect symbol base, if necessary.
566*0fca6ea1SDimitry Andric     IndirectSymBase.insert(std::make_pair(ISD.Section, IndirectIndex));
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric     // Set the symbol type to undefined lazy, but only on construction.
5690b57cec5SDimitry Andric     //
5700b57cec5SDimitry Andric     // FIXME: Do not hardcode.
571*0fca6ea1SDimitry Andric     if (Asm.registerSymbol(*ISD.Symbol))
572*0fca6ea1SDimitry Andric       cast<MCSymbolMachO>(ISD.Symbol)->setReferenceTypeUndefinedLazy(true);
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric /// computeSymbolTable - Compute the symbol table data
5770b57cec5SDimitry Andric void MachObjectWriter::computeSymbolTable(
5780b57cec5SDimitry Andric     MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData,
5790b57cec5SDimitry Andric     std::vector<MachSymbolData> &ExternalSymbolData,
5800b57cec5SDimitry Andric     std::vector<MachSymbolData> &UndefinedSymbolData) {
5810b57cec5SDimitry Andric   // Build section lookup table.
5820b57cec5SDimitry Andric   DenseMap<const MCSection*, uint8_t> SectionIndexMap;
5830b57cec5SDimitry Andric   unsigned Index = 1;
584*0fca6ea1SDimitry Andric   for (MCSection &Sec : Asm)
585*0fca6ea1SDimitry Andric     SectionIndexMap[&Sec] = Index++;
5860b57cec5SDimitry Andric   assert(Index <= 256 && "Too many sections!");
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   // Build the string table.
5890b57cec5SDimitry Andric   for (const MCSymbol &Symbol : Asm.symbols()) {
590*0fca6ea1SDimitry Andric     if (!cast<MCSymbolMachO>(Symbol).isSymbolLinkerVisible())
5910b57cec5SDimitry Andric       continue;
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric     StringTable.add(Symbol.getName());
5940b57cec5SDimitry Andric   }
5950b57cec5SDimitry Andric   StringTable.finalize();
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   // Build the symbol arrays but only for non-local symbols.
5980b57cec5SDimitry Andric   //
5990b57cec5SDimitry Andric   // The particular order that we collect and then sort the symbols is chosen to
6000b57cec5SDimitry Andric   // match 'as'. Even though it doesn't matter for correctness, this is
6010b57cec5SDimitry Andric   // important for letting us diff .o files.
6020b57cec5SDimitry Andric   for (const MCSymbol &Symbol : Asm.symbols()) {
6030b57cec5SDimitry Andric     // Ignore non-linker visible symbols.
604*0fca6ea1SDimitry Andric     if (!cast<MCSymbolMachO>(Symbol).isSymbolLinkerVisible())
6050b57cec5SDimitry Andric       continue;
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric     if (!Symbol.isExternal() && !Symbol.isUndefined())
6080b57cec5SDimitry Andric       continue;
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric     MachSymbolData MSD;
6110b57cec5SDimitry Andric     MSD.Symbol = &Symbol;
6120b57cec5SDimitry Andric     MSD.StringIndex = StringTable.getOffset(Symbol.getName());
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric     if (Symbol.isUndefined()) {
6150b57cec5SDimitry Andric       MSD.SectionIndex = 0;
6160b57cec5SDimitry Andric       UndefinedSymbolData.push_back(MSD);
6170b57cec5SDimitry Andric     } else if (Symbol.isAbsolute()) {
6180b57cec5SDimitry Andric       MSD.SectionIndex = 0;
6190b57cec5SDimitry Andric       ExternalSymbolData.push_back(MSD);
6200b57cec5SDimitry Andric     } else {
6210b57cec5SDimitry Andric       MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
6220b57cec5SDimitry Andric       assert(MSD.SectionIndex && "Invalid section index!");
6230b57cec5SDimitry Andric       ExternalSymbolData.push_back(MSD);
6240b57cec5SDimitry Andric     }
6250b57cec5SDimitry Andric   }
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric   // Now add the data for local symbols.
6280b57cec5SDimitry Andric   for (const MCSymbol &Symbol : Asm.symbols()) {
6290b57cec5SDimitry Andric     // Ignore non-linker visible symbols.
630*0fca6ea1SDimitry Andric     if (!cast<MCSymbolMachO>(Symbol).isSymbolLinkerVisible())
6310b57cec5SDimitry Andric       continue;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric     if (Symbol.isExternal() || Symbol.isUndefined())
6340b57cec5SDimitry Andric       continue;
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric     MachSymbolData MSD;
6370b57cec5SDimitry Andric     MSD.Symbol = &Symbol;
6380b57cec5SDimitry Andric     MSD.StringIndex = StringTable.getOffset(Symbol.getName());
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric     if (Symbol.isAbsolute()) {
6410b57cec5SDimitry Andric       MSD.SectionIndex = 0;
6420b57cec5SDimitry Andric       LocalSymbolData.push_back(MSD);
6430b57cec5SDimitry Andric     } else {
6440b57cec5SDimitry Andric       MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
6450b57cec5SDimitry Andric       assert(MSD.SectionIndex && "Invalid section index!");
6460b57cec5SDimitry Andric       LocalSymbolData.push_back(MSD);
6470b57cec5SDimitry Andric     }
6480b57cec5SDimitry Andric   }
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   // External and undefined symbols are required to be in lexicographic order.
6510b57cec5SDimitry Andric   llvm::sort(ExternalSymbolData);
6520b57cec5SDimitry Andric   llvm::sort(UndefinedSymbolData);
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   // Set the symbol indices.
6550b57cec5SDimitry Andric   Index = 0;
6560b57cec5SDimitry Andric   for (auto *SymbolData :
6570b57cec5SDimitry Andric        {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
6580b57cec5SDimitry Andric     for (MachSymbolData &Entry : *SymbolData)
6590b57cec5SDimitry Andric       Entry.Symbol->setIndex(Index++);
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   for (const MCSection &Section : Asm) {
6620b57cec5SDimitry Andric     for (RelAndSymbol &Rel : Relocations[&Section]) {
6630b57cec5SDimitry Andric       if (!Rel.Sym)
6640b57cec5SDimitry Andric         continue;
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric       // Set the Index and the IsExtern bit.
6670b57cec5SDimitry Andric       unsigned Index = Rel.Sym->getIndex();
6680b57cec5SDimitry Andric       assert(isInt<24>(Index));
6695f757f3fSDimitry Andric       if (W.Endian == llvm::endianness::little)
6700b57cec5SDimitry Andric         Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);
6710b57cec5SDimitry Andric       else
6720b57cec5SDimitry Andric         Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
6730b57cec5SDimitry Andric     }
6740b57cec5SDimitry Andric   }
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric 
677*0fca6ea1SDimitry Andric void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm) {
678*0fca6ea1SDimitry Andric   // Assign layout order indices to sections.
679*0fca6ea1SDimitry Andric   unsigned i = 0;
680*0fca6ea1SDimitry Andric   // Compute the section layout order. Virtual sections must go last.
681*0fca6ea1SDimitry Andric   for (MCSection &Sec : Asm) {
682*0fca6ea1SDimitry Andric     if (!Sec.isVirtualSection()) {
683*0fca6ea1SDimitry Andric       SectionOrder.push_back(&Sec);
684*0fca6ea1SDimitry Andric       cast<MCSectionMachO>(Sec).setLayoutOrder(i++);
685*0fca6ea1SDimitry Andric     }
686*0fca6ea1SDimitry Andric   }
687*0fca6ea1SDimitry Andric   for (MCSection &Sec : Asm) {
688*0fca6ea1SDimitry Andric     if (Sec.isVirtualSection()) {
689*0fca6ea1SDimitry Andric       SectionOrder.push_back(&Sec);
690*0fca6ea1SDimitry Andric       cast<MCSectionMachO>(Sec).setLayoutOrder(i++);
691*0fca6ea1SDimitry Andric     }
692*0fca6ea1SDimitry Andric   }
693*0fca6ea1SDimitry Andric 
6940b57cec5SDimitry Andric   uint64_t StartAddress = 0;
695*0fca6ea1SDimitry Andric   for (const MCSection *Sec : SectionOrder) {
696bdd1243dSDimitry Andric     StartAddress = alignTo(StartAddress, Sec->getAlign());
6970b57cec5SDimitry Andric     SectionAddress[Sec] = StartAddress;
698*0fca6ea1SDimitry Andric     StartAddress += Asm.getSectionAddressSize(*Sec);
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric     // Explicitly pad the section to match the alignment requirements of the
7010b57cec5SDimitry Andric     // following one. This is for 'gas' compatibility, it shouldn't
7020b57cec5SDimitry Andric     /// strictly be necessary.
703*0fca6ea1SDimitry Andric     StartAddress += getPaddingSize(Asm, Sec);
7040b57cec5SDimitry Andric   }
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric 
707*0fca6ea1SDimitry Andric void MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm) {
708*0fca6ea1SDimitry Andric   computeSectionAddresses(Asm);
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   // Create symbol data for any indirect symbols.
7110b57cec5SDimitry Andric   bindIndirectSymbols(Asm);
7120b57cec5SDimitry Andric }
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
7150b57cec5SDimitry Andric     const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
7160b57cec5SDimitry Andric     bool InSet, bool IsPCRel) const {
7170b57cec5SDimitry Andric   if (InSet)
7180b57cec5SDimitry Andric     return true;
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric   // The effective address is
7210b57cec5SDimitry Andric   //     addr(atom(A)) + offset(A)
7220b57cec5SDimitry Andric   //   - addr(atom(B)) - offset(B)
7230b57cec5SDimitry Andric   // and the offsets are not relocatable, so the fixup is fully resolved when
7240b57cec5SDimitry Andric   //  addr(atom(A)) - addr(atom(B)) == 0.
7250b57cec5SDimitry Andric   const MCSymbol &SA = findAliasedSymbol(SymA);
7260b57cec5SDimitry Andric   const MCSection &SecA = SA.getSection();
7270b57cec5SDimitry Andric   const MCSection &SecB = *FB.getParent();
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   if (IsPCRel) {
7300b57cec5SDimitry Andric     // The simple (Darwin, except on x86_64) way of dealing with this was to
7310b57cec5SDimitry Andric     // assume that any reference to a temporary symbol *must* be a temporary
7320b57cec5SDimitry Andric     // symbol in the same atom, unless the sections differ. Therefore, any PCrel
7330b57cec5SDimitry Andric     // relocation to a temporary symbol (in the same section) is fully
7340b57cec5SDimitry Andric     // resolved. This also works in conjunction with absolutized .set, which
7350b57cec5SDimitry Andric     // requires the compiler to use .set to absolutize the differences between
7360b57cec5SDimitry Andric     // symbols which the compiler knows to be assembly time constants, so we
7370b57cec5SDimitry Andric     // don't need to worry about considering symbol differences fully resolved.
7380b57cec5SDimitry Andric     //
7390b57cec5SDimitry Andric     // If the file isn't using sub-sections-via-symbols, we can make the
7400b57cec5SDimitry Andric     // same assumptions about any symbol that we normally make about
7410b57cec5SDimitry Andric     // assembler locals.
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric     bool hasReliableSymbolDifference = isX86_64();
7440b57cec5SDimitry Andric     if (!hasReliableSymbolDifference) {
7450b57cec5SDimitry Andric       if (!SA.isInSection() || &SecA != &SecB ||
7460b57cec5SDimitry Andric           (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() &&
747*0fca6ea1SDimitry Andric            SubsectionsViaSymbols))
7480b57cec5SDimitry Andric         return false;
7490b57cec5SDimitry Andric       return true;
7500b57cec5SDimitry Andric     }
7510b57cec5SDimitry Andric   }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   // If they are not in the same section, we can't compute the diff.
7540b57cec5SDimitry Andric   if (&SecA != &SecB)
7550b57cec5SDimitry Andric     return false;
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   // If the atoms are the same, they are guaranteed to have the same address.
758*0fca6ea1SDimitry Andric   return SA.getFragment()->getAtom() == FB.getAtom();
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
7620b57cec5SDimitry Andric   switch (Type) {
7630b57cec5SDimitry Andric   case MCVM_OSXVersionMin:     return MachO::LC_VERSION_MIN_MACOSX;
7640b57cec5SDimitry Andric   case MCVM_IOSVersionMin:     return MachO::LC_VERSION_MIN_IPHONEOS;
7650b57cec5SDimitry Andric   case MCVM_TvOSVersionMin:    return MachO::LC_VERSION_MIN_TVOS;
7660b57cec5SDimitry Andric   case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS;
7670b57cec5SDimitry Andric   }
7680b57cec5SDimitry Andric   llvm_unreachable("Invalid mc version min type");
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric 
771fcaf7f86SDimitry Andric void MachObjectWriter::populateAddrSigSection(MCAssembler &Asm) {
77281ad6265SDimitry Andric   MCSection *AddrSigSection =
77381ad6265SDimitry Andric       Asm.getContext().getObjectFileInfo()->getAddrSigSection();
774fcaf7f86SDimitry Andric   unsigned Log2Size = is64Bit() ? 3 : 2;
775fcaf7f86SDimitry Andric   for (const MCSymbol *S : getAddrsigSyms()) {
776bdd1243dSDimitry Andric     if (!S->isRegistered())
777bdd1243dSDimitry Andric       continue;
778fcaf7f86SDimitry Andric     MachO::any_relocation_info MRE;
779fcaf7f86SDimitry Andric     MRE.r_word0 = 0;
780fcaf7f86SDimitry Andric     MRE.r_word1 = (Log2Size << 25) | (MachO::GENERIC_RELOC_VANILLA << 28);
781fcaf7f86SDimitry Andric     addRelocation(S, AddrSigSection, MRE);
782fcaf7f86SDimitry Andric   }
78381ad6265SDimitry Andric }
78481ad6265SDimitry Andric 
785*0fca6ea1SDimitry Andric uint64_t MachObjectWriter::writeObject(MCAssembler &Asm) {
7860b57cec5SDimitry Andric   uint64_t StartOffset = W.OS.tell();
787*0fca6ea1SDimitry Andric   auto NumBytesWritten = [&] { return W.OS.tell() - StartOffset; };
7880b57cec5SDimitry Andric 
789fcaf7f86SDimitry Andric   populateAddrSigSection(Asm);
790fcaf7f86SDimitry Andric 
7910b57cec5SDimitry Andric   // Compute symbol table information and bind symbol indices.
7920b57cec5SDimitry Andric   computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
7930b57cec5SDimitry Andric                      UndefinedSymbolData);
7940b57cec5SDimitry Andric 
795*0fca6ea1SDimitry Andric   if (!CGProfile.empty()) {
79604eeddc0SDimitry Andric     MCSection *CGProfileSection = Asm.getContext().getMachOSection(
79704eeddc0SDimitry Andric         "__LLVM", "__cg_profile", 0, SectionKind::getMetadata());
798*0fca6ea1SDimitry Andric     auto &Frag = cast<MCDataFragment>(*CGProfileSection->begin());
799*0fca6ea1SDimitry Andric     Frag.getContents().clear();
800*0fca6ea1SDimitry Andric     raw_svector_ostream OS(Frag.getContents());
801*0fca6ea1SDimitry Andric     for (const MCObjectWriter::CGProfileEntry &CGPE : CGProfile) {
80204eeddc0SDimitry Andric       uint32_t FromIndex = CGPE.From->getSymbol().getIndex();
80304eeddc0SDimitry Andric       uint32_t ToIndex = CGPE.To->getSymbol().getIndex();
80404eeddc0SDimitry Andric       support::endian::write(OS, FromIndex, W.Endian);
80504eeddc0SDimitry Andric       support::endian::write(OS, ToIndex, W.Endian);
80604eeddc0SDimitry Andric       support::endian::write(OS, CGPE.Count, W.Endian);
80704eeddc0SDimitry Andric     }
80804eeddc0SDimitry Andric   }
80904eeddc0SDimitry Andric 
810*0fca6ea1SDimitry Andric   unsigned NumSections = Asm.end() - Asm.begin();
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric   // The section data starts after the header, the segment load command (and
8130b57cec5SDimitry Andric   // section headers) and the symbol table.
8140b57cec5SDimitry Andric   unsigned NumLoadCommands = 1;
8150b57cec5SDimitry Andric   uint64_t LoadCommandsSize = is64Bit() ?
8160b57cec5SDimitry Andric     sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):
8170b57cec5SDimitry Andric     sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   // Add the deployment target version info load command size, if used.
8200b57cec5SDimitry Andric   if (VersionInfo.Major != 0) {
8210b57cec5SDimitry Andric     ++NumLoadCommands;
8220b57cec5SDimitry Andric     if (VersionInfo.EmitBuildVersion)
8230b57cec5SDimitry Andric       LoadCommandsSize += sizeof(MachO::build_version_command);
8240b57cec5SDimitry Andric     else
8250b57cec5SDimitry Andric       LoadCommandsSize += sizeof(MachO::version_min_command);
8260b57cec5SDimitry Andric   }
8270b57cec5SDimitry Andric 
8280eae32dcSDimitry Andric   // Add the target variant version info load command size, if used.
8290eae32dcSDimitry Andric   if (TargetVariantVersionInfo.Major != 0) {
8300eae32dcSDimitry Andric     ++NumLoadCommands;
8310eae32dcSDimitry Andric     assert(TargetVariantVersionInfo.EmitBuildVersion &&
8320eae32dcSDimitry Andric            "target variant should use build version");
8330eae32dcSDimitry Andric     LoadCommandsSize += sizeof(MachO::build_version_command);
8340eae32dcSDimitry Andric   }
8350eae32dcSDimitry Andric 
8360b57cec5SDimitry Andric   // Add the data-in-code load command size, if used.
837*0fca6ea1SDimitry Andric   unsigned NumDataRegions = DataRegions.size();
8380b57cec5SDimitry Andric   if (NumDataRegions) {
8390b57cec5SDimitry Andric     ++NumLoadCommands;
8400b57cec5SDimitry Andric     LoadCommandsSize += sizeof(MachO::linkedit_data_command);
8410b57cec5SDimitry Andric   }
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric   // Add the loh load command size, if used.
844*0fca6ea1SDimitry Andric   uint64_t LOHRawSize = LOHContainer.getEmitSize(Asm, *this);
8450b57cec5SDimitry Andric   uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4);
8460b57cec5SDimitry Andric   if (LOHSize) {
8470b57cec5SDimitry Andric     ++NumLoadCommands;
8480b57cec5SDimitry Andric     LoadCommandsSize += sizeof(MachO::linkedit_data_command);
8490b57cec5SDimitry Andric   }
8500b57cec5SDimitry Andric 
8510b57cec5SDimitry Andric   // Add the symbol table load command sizes, if used.
8520b57cec5SDimitry Andric   unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
8530b57cec5SDimitry Andric     UndefinedSymbolData.size();
8540b57cec5SDimitry Andric   if (NumSymbols) {
8550b57cec5SDimitry Andric     NumLoadCommands += 2;
8560b57cec5SDimitry Andric     LoadCommandsSize += (sizeof(MachO::symtab_command) +
8570b57cec5SDimitry Andric                          sizeof(MachO::dysymtab_command));
8580b57cec5SDimitry Andric   }
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric   // Add the linker option load commands sizes.
861*0fca6ea1SDimitry Andric   for (const auto &Option : LinkerOptions) {
8620b57cec5SDimitry Andric     ++NumLoadCommands;
8630b57cec5SDimitry Andric     LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(Option, is64Bit());
8640b57cec5SDimitry Andric   }
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric   // Compute the total size of the section data, as well as its file size and vm
8670b57cec5SDimitry Andric   // size.
8680b57cec5SDimitry Andric   uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) :
8690b57cec5SDimitry Andric                                sizeof(MachO::mach_header)) + LoadCommandsSize;
8700b57cec5SDimitry Andric   uint64_t SectionDataSize = 0;
8710b57cec5SDimitry Andric   uint64_t SectionDataFileSize = 0;
8720b57cec5SDimitry Andric   uint64_t VMSize = 0;
8730b57cec5SDimitry Andric   for (const MCSection &Sec : Asm) {
8740b57cec5SDimitry Andric     uint64_t Address = getSectionAddress(&Sec);
875*0fca6ea1SDimitry Andric     uint64_t Size = Asm.getSectionAddressSize(Sec);
876*0fca6ea1SDimitry Andric     uint64_t FileSize = Asm.getSectionFileSize(Sec);
877*0fca6ea1SDimitry Andric     FileSize += getPaddingSize(Asm, &Sec);
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric     VMSize = std::max(VMSize, Address + Size);
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric     if (Sec.isVirtualSection())
8820b57cec5SDimitry Andric       continue;
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric     SectionDataSize = std::max(SectionDataSize, Address + Size);
8850b57cec5SDimitry Andric     SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
8860b57cec5SDimitry Andric   }
8870b57cec5SDimitry Andric 
8885ffd83dbSDimitry Andric   // The section data is padded to pointer size bytes.
8890b57cec5SDimitry Andric   //
8900b57cec5SDimitry Andric   // FIXME: Is this machine dependent?
8918bcb0991SDimitry Andric   unsigned SectionDataPadding =
8925ffd83dbSDimitry Andric       offsetToAlignment(SectionDataFileSize, is64Bit() ? Align(8) : Align(4));
8930b57cec5SDimitry Andric   SectionDataFileSize += SectionDataPadding;
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   // Write the prolog, starting with the header and load command...
8960b57cec5SDimitry Andric   writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize,
897*0fca6ea1SDimitry Andric               SubsectionsViaSymbols);
8980b57cec5SDimitry Andric   uint32_t Prot =
8990b57cec5SDimitry Andric       MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
9000b57cec5SDimitry Andric   writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart,
9010b57cec5SDimitry Andric                           SectionDataSize, Prot, Prot);
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric   // ... and then the section headers.
9040b57cec5SDimitry Andric   uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
9050b57cec5SDimitry Andric   for (const MCSection &Section : Asm) {
9060b57cec5SDimitry Andric     const auto &Sec = cast<MCSectionMachO>(Section);
9070b57cec5SDimitry Andric     std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
9080b57cec5SDimitry Andric     unsigned NumRelocs = Relocs.size();
9090b57cec5SDimitry Andric     uint64_t SectionStart = SectionDataStart + getSectionAddress(&Sec);
9100b57cec5SDimitry Andric     unsigned Flags = Sec.getTypeAndAttributes();
9110b57cec5SDimitry Andric     if (Sec.hasInstructions())
9120b57cec5SDimitry Andric       Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS;
913*0fca6ea1SDimitry Andric     if (!cast<MCSectionMachO>(Sec).isVirtualSection() &&
914*0fca6ea1SDimitry Andric         !isUInt<32>(SectionStart)) {
915*0fca6ea1SDimitry Andric       Asm.getContext().reportError(
916*0fca6ea1SDimitry Andric           SMLoc(), "cannot encode offset of section; object file too large");
917*0fca6ea1SDimitry Andric       return NumBytesWritten();
918*0fca6ea1SDimitry Andric     }
919*0fca6ea1SDimitry Andric     if (NumRelocs && !isUInt<32>(RelocTableEnd)) {
920*0fca6ea1SDimitry Andric       Asm.getContext().reportError(
921*0fca6ea1SDimitry Andric           SMLoc(),
922*0fca6ea1SDimitry Andric           "cannot encode offset of relocations; object file too large");
923*0fca6ea1SDimitry Andric       return NumBytesWritten();
924*0fca6ea1SDimitry Andric     }
925*0fca6ea1SDimitry Andric     writeSection(Asm, Sec, getSectionAddress(&Sec), SectionStart, Flags,
9260b57cec5SDimitry Andric                  RelocTableEnd, NumRelocs);
9270b57cec5SDimitry Andric     RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);
9280b57cec5SDimitry Andric   }
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric   // Write out the deployment target information, if it's available.
9310eae32dcSDimitry Andric   auto EmitDeploymentTargetVersion =
932*0fca6ea1SDimitry Andric       [&](const VersionInfoType &VersionInfo) {
9330b57cec5SDimitry Andric         auto EncodeVersion = [](VersionTuple V) -> uint32_t {
9340b57cec5SDimitry Andric           assert(!V.empty() && "empty version");
93581ad6265SDimitry Andric           unsigned Update = V.getSubminor().value_or(0);
93681ad6265SDimitry Andric           unsigned Minor = V.getMinor().value_or(0);
9370b57cec5SDimitry Andric           assert(Update < 256 && "unencodable update target version");
9380b57cec5SDimitry Andric           assert(Minor < 256 && "unencodable minor target version");
9390b57cec5SDimitry Andric           assert(V.getMajor() < 65536 && "unencodable major target version");
9400b57cec5SDimitry Andric           return Update | (Minor << 8) | (V.getMajor() << 16);
9410b57cec5SDimitry Andric         };
9420eae32dcSDimitry Andric         uint32_t EncodedVersion = EncodeVersion(VersionTuple(
9430eae32dcSDimitry Andric             VersionInfo.Major, VersionInfo.Minor, VersionInfo.Update));
9440b57cec5SDimitry Andric         uint32_t SDKVersion = !VersionInfo.SDKVersion.empty()
9450b57cec5SDimitry Andric                                   ? EncodeVersion(VersionInfo.SDKVersion)
9460b57cec5SDimitry Andric                                   : 0;
9470b57cec5SDimitry Andric         if (VersionInfo.EmitBuildVersion) {
9480b57cec5SDimitry Andric           // FIXME: Currently empty tools. Add clang version in the future.
9490b57cec5SDimitry Andric           W.write<uint32_t>(MachO::LC_BUILD_VERSION);
9500b57cec5SDimitry Andric           W.write<uint32_t>(sizeof(MachO::build_version_command));
9510b57cec5SDimitry Andric           W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);
9520b57cec5SDimitry Andric           W.write<uint32_t>(EncodedVersion);
9530b57cec5SDimitry Andric           W.write<uint32_t>(SDKVersion);
9540b57cec5SDimitry Andric           W.write<uint32_t>(0); // Empty tools list.
9550b57cec5SDimitry Andric         } else {
9560eae32dcSDimitry Andric           MachO::LoadCommandType LCType =
9570eae32dcSDimitry Andric               getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
9580b57cec5SDimitry Andric           W.write<uint32_t>(LCType);
9590b57cec5SDimitry Andric           W.write<uint32_t>(sizeof(MachO::version_min_command));
9600b57cec5SDimitry Andric           W.write<uint32_t>(EncodedVersion);
9610b57cec5SDimitry Andric           W.write<uint32_t>(SDKVersion);
9620b57cec5SDimitry Andric         }
9630eae32dcSDimitry Andric       };
9640eae32dcSDimitry Andric   if (VersionInfo.Major != 0)
9650eae32dcSDimitry Andric     EmitDeploymentTargetVersion(VersionInfo);
9660eae32dcSDimitry Andric   if (TargetVariantVersionInfo.Major != 0)
9670eae32dcSDimitry Andric     EmitDeploymentTargetVersion(TargetVariantVersionInfo);
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric   // Write the data-in-code load command, if used.
9700b57cec5SDimitry Andric   uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
9710b57cec5SDimitry Andric   if (NumDataRegions) {
9720b57cec5SDimitry Andric     uint64_t DataRegionsOffset = RelocTableEnd;
9730b57cec5SDimitry Andric     uint64_t DataRegionsSize = NumDataRegions * 8;
9740b57cec5SDimitry Andric     writeLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset,
9750b57cec5SDimitry Andric                              DataRegionsSize);
9760b57cec5SDimitry Andric   }
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric   // Write the loh load command, if used.
9790b57cec5SDimitry Andric   uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize;
9800b57cec5SDimitry Andric   if (LOHSize)
9810b57cec5SDimitry Andric     writeLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT,
9820b57cec5SDimitry Andric                              DataInCodeTableEnd, LOHSize);
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric   // Write the symbol table load command, if used.
9850b57cec5SDimitry Andric   if (NumSymbols) {
9860b57cec5SDimitry Andric     unsigned FirstLocalSymbol = 0;
9870b57cec5SDimitry Andric     unsigned NumLocalSymbols = LocalSymbolData.size();
9880b57cec5SDimitry Andric     unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
9890b57cec5SDimitry Andric     unsigned NumExternalSymbols = ExternalSymbolData.size();
9900b57cec5SDimitry Andric     unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
9910b57cec5SDimitry Andric     unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
992*0fca6ea1SDimitry Andric     unsigned NumIndirectSymbols = IndirectSymbols.size();
9930b57cec5SDimitry Andric     unsigned NumSymTabSymbols =
9940b57cec5SDimitry Andric       NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
9950b57cec5SDimitry Andric     uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
9960b57cec5SDimitry Andric     uint64_t IndirectSymbolOffset = 0;
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric     // If used, the indirect symbols are written after the section data.
9990b57cec5SDimitry Andric     if (NumIndirectSymbols)
10000b57cec5SDimitry Andric       IndirectSymbolOffset = LOHTableEnd;
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric     // The symbol table is written after the indirect symbol data.
10030b57cec5SDimitry Andric     uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize;
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric     // The string table is written after symbol table.
10060b57cec5SDimitry Andric     uint64_t StringTableOffset =
10070b57cec5SDimitry Andric       SymbolTableOffset + NumSymTabSymbols * (is64Bit() ?
10080b57cec5SDimitry Andric                                               sizeof(MachO::nlist_64) :
10090b57cec5SDimitry Andric                                               sizeof(MachO::nlist));
10100b57cec5SDimitry Andric     writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
10110b57cec5SDimitry Andric                            StringTableOffset, StringTable.getSize());
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric     writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
10140b57cec5SDimitry Andric                              FirstExternalSymbol, NumExternalSymbols,
10150b57cec5SDimitry Andric                              FirstUndefinedSymbol, NumUndefinedSymbols,
10160b57cec5SDimitry Andric                              IndirectSymbolOffset, NumIndirectSymbols);
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   // Write the linker options load commands.
1020*0fca6ea1SDimitry Andric   for (const auto &Option : LinkerOptions)
10210b57cec5SDimitry Andric     writeLinkerOptionsLoadCommand(Option);
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   // Write the actual section data.
10240b57cec5SDimitry Andric   for (const MCSection &Sec : Asm) {
1025*0fca6ea1SDimitry Andric     Asm.writeSectionData(W.OS, &Sec);
10260b57cec5SDimitry Andric 
1027*0fca6ea1SDimitry Andric     uint64_t Pad = getPaddingSize(Asm, &Sec);
10280b57cec5SDimitry Andric     W.OS.write_zeros(Pad);
10290b57cec5SDimitry Andric   }
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   // Write the extra padding.
10320b57cec5SDimitry Andric   W.OS.write_zeros(SectionDataPadding);
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   // Write the relocation entries.
10350b57cec5SDimitry Andric   for (const MCSection &Sec : Asm) {
10360b57cec5SDimitry Andric     // Write the section relocation entries, in reverse order to match 'as'
10370b57cec5SDimitry Andric     // (approximately, the exact algorithm is more complicated than this).
10380b57cec5SDimitry Andric     std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
1039349cc55cSDimitry Andric     for (const RelAndSymbol &Rel : llvm::reverse(Relocs)) {
10400b57cec5SDimitry Andric       W.write<uint32_t>(Rel.MRE.r_word0);
10410b57cec5SDimitry Andric       W.write<uint32_t>(Rel.MRE.r_word1);
10420b57cec5SDimitry Andric     }
10430b57cec5SDimitry Andric   }
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric   // Write out the data-in-code region payload, if there is one.
1046*0fca6ea1SDimitry Andric   for (DataRegionData Data : DataRegions) {
1047*0fca6ea1SDimitry Andric     uint64_t Start = getSymbolAddress(*Data.Start, Asm);
10480b57cec5SDimitry Andric     uint64_t End;
1049*0fca6ea1SDimitry Andric     if (Data.End)
1050*0fca6ea1SDimitry Andric       End = getSymbolAddress(*Data.End, Asm);
10510b57cec5SDimitry Andric     else
10520b57cec5SDimitry Andric       report_fatal_error("Data region not terminated");
10530b57cec5SDimitry Andric 
1054*0fca6ea1SDimitry Andric     LLVM_DEBUG(dbgs() << "data in code region-- kind: " << Data.Kind
1055*0fca6ea1SDimitry Andric                       << "  start: " << Start << "(" << Data.Start->getName()
1056*0fca6ea1SDimitry Andric                       << ")" << "  end: " << End << "(" << Data.End->getName()
1057*0fca6ea1SDimitry Andric                       << ")" << "  size: " << End - Start << "\n");
10580b57cec5SDimitry Andric     W.write<uint32_t>(Start);
10590b57cec5SDimitry Andric     W.write<uint16_t>(End - Start);
1060*0fca6ea1SDimitry Andric     W.write<uint16_t>(Data.Kind);
10610b57cec5SDimitry Andric   }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   // Write out the loh commands, if there is one.
10640b57cec5SDimitry Andric   if (LOHSize) {
10650b57cec5SDimitry Andric #ifndef NDEBUG
10660b57cec5SDimitry Andric     unsigned Start = W.OS.tell();
10670b57cec5SDimitry Andric #endif
1068*0fca6ea1SDimitry Andric     LOHContainer.emit(Asm, *this);
10690b57cec5SDimitry Andric     // Pad to a multiple of the pointer size.
10708bcb0991SDimitry Andric     W.OS.write_zeros(
10718bcb0991SDimitry Andric         offsetToAlignment(LOHRawSize, is64Bit() ? Align(8) : Align(4)));
10720b57cec5SDimitry Andric     assert(W.OS.tell() - Start == LOHSize);
10730b57cec5SDimitry Andric   }
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric   // Write the symbol table data, if used.
10760b57cec5SDimitry Andric   if (NumSymbols) {
10770b57cec5SDimitry Andric     // Write the indirect symbol entries.
1078*0fca6ea1SDimitry Andric     for (auto &ISD : IndirectSymbols) {
10790b57cec5SDimitry Andric       // Indirect symbols in the non-lazy symbol pointer section have some
10800b57cec5SDimitry Andric       // special handling.
10810b57cec5SDimitry Andric       const MCSectionMachO &Section =
1082*0fca6ea1SDimitry Andric           static_cast<const MCSectionMachO &>(*ISD.Section);
10830b57cec5SDimitry Andric       if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) {
10840b57cec5SDimitry Andric         // If this symbol is defined and internal, mark it as such.
1085*0fca6ea1SDimitry Andric         if (ISD.Symbol->isDefined() && !ISD.Symbol->isExternal()) {
10860b57cec5SDimitry Andric           uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
1087*0fca6ea1SDimitry Andric           if (ISD.Symbol->isAbsolute())
10880b57cec5SDimitry Andric             Flags |= MachO::INDIRECT_SYMBOL_ABS;
10890b57cec5SDimitry Andric           W.write<uint32_t>(Flags);
10900b57cec5SDimitry Andric           continue;
10910b57cec5SDimitry Andric         }
10920b57cec5SDimitry Andric       }
10930b57cec5SDimitry Andric 
1094*0fca6ea1SDimitry Andric       W.write<uint32_t>(ISD.Symbol->getIndex());
10950b57cec5SDimitry Andric     }
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric     // FIXME: Check that offsets match computed ones.
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric     // Write the symbol table entries.
11000b57cec5SDimitry Andric     for (auto *SymbolData :
11010b57cec5SDimitry Andric          {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
11020b57cec5SDimitry Andric       for (MachSymbolData &Entry : *SymbolData)
1103*0fca6ea1SDimitry Andric         writeNlist(Entry, Asm);
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric     // Write the string table.
11060b57cec5SDimitry Andric     StringTable.write(W.OS);
11070b57cec5SDimitry Andric   }
11080b57cec5SDimitry Andric 
1109*0fca6ea1SDimitry Andric   return NumBytesWritten();
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter>
11130b57cec5SDimitry Andric llvm::createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
11140b57cec5SDimitry Andric                              raw_pwrite_stream &OS, bool IsLittleEndian) {
11158bcb0991SDimitry Andric   return std::make_unique<MachObjectWriter>(std::move(MOTW), OS,
11160b57cec5SDimitry Andric                                              IsLittleEndian);
11170b57cec5SDimitry Andric }
1118