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