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