529 lines · cpp
1//===- MCMachOStreamer.cpp - MachO Streamer -------------------------------===//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/SmallVector.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/BinaryFormat/MachO.h"13#include "llvm/MC/MCAsmBackend.h"14#include "llvm/MC/MCAssembler.h"15#include "llvm/MC/MCCodeEmitter.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCDirectives.h"18#include "llvm/MC/MCExpr.h"19#include "llvm/MC/MCFixup.h"20#include "llvm/MC/MCLinkerOptimizationHint.h"21#include "llvm/MC/MCMachObjectWriter.h"22#include "llvm/MC/MCObjectFileInfo.h"23#include "llvm/MC/MCObjectStreamer.h"24#include "llvm/MC/MCObjectWriter.h"25#include "llvm/MC/MCSection.h"26#include "llvm/MC/MCSectionMachO.h"27#include "llvm/MC/MCSymbol.h"28#include "llvm/MC/MCSymbolMachO.h"29#include "llvm/MC/MCValue.h"30#include "llvm/MC/SectionKind.h"31#include "llvm/MC/TargetRegistry.h"32#include "llvm/Support/Casting.h"33#include "llvm/Support/ErrorHandling.h"34#include <cassert>35#include <vector>36 37namespace llvm {38class MCInst;39class MCStreamer;40class MCSubtargetInfo;41class Triple;42} // namespace llvm43 44using namespace llvm;45 46namespace {47 48class MCMachOStreamer : public MCObjectStreamer {49private:50 /// LabelSections - true if each section change should emit a linker local51 /// label for use in relocations for assembler local references. Obviates the52 /// need for local relocations. False by default.53 bool LabelSections;54 55 /// HasSectionLabel - map of which sections have already had a non-local56 /// label emitted to them. Used so we don't emit extraneous linker local57 /// labels in the middle of the section.58 DenseMap<const MCSection*, bool> HasSectionLabel;59 60 void emitDataRegion(MachO::DataRegionType Kind);61 void emitDataRegionEnd();62 63public:64 MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,65 std::unique_ptr<MCObjectWriter> OW,66 std::unique_ptr<MCCodeEmitter> Emitter, bool label)67 : MCObjectStreamer(Context, std::move(MAB), std::move(OW),68 std::move(Emitter)),69 LabelSections(label) {}70 71 /// state management72 void reset() override {73 HasSectionLabel.clear();74 MCObjectStreamer::reset();75 }76 77 MachObjectWriter &getWriter() {78 return static_cast<MachObjectWriter &>(getAssembler().getWriter());79 }80 81 /// @name MCStreamer Interface82 /// @{83 84 void changeSection(MCSection *Sect, uint32_t Subsection = 0) override;85 void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;86 void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;87 void emitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;88 void emitSubsectionsViaSymbols() override;89 void emitLinkerOptions(ArrayRef<std::string> Options) override;90 void emitDataRegion(MCDataRegionType Kind) override;91 void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,92 unsigned Update, VersionTuple SDKVersion) override;93 void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,94 unsigned Update, VersionTuple SDKVersion) override;95 void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,96 unsigned Minor, unsigned Update,97 VersionTuple SDKVersion) override;98 bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;99 void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;100 void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,101 Align ByteAlignment) override;102 103 void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,104 Align ByteAlignment) override;105 void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,106 uint64_t Size = 0, Align ByteAlignment = Align(1),107 SMLoc Loc = SMLoc()) override;108 void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,109 Align ByteAlignment = Align(1)) override;110 111 void emitIdent(StringRef IdentString) override {112 llvm_unreachable("macho doesn't support this directive");113 }114 115 void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {116 getWriter().getLOHContainer().addDirective(Kind, Args);117 }118 void emitCGProfileEntry(const MCSymbolRefExpr *From,119 const MCSymbolRefExpr *To, uint64_t Count) override {120 if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())121 getWriter().getCGProfile().push_back({From, To, Count});122 }123 124 void finishImpl() override;125 126 void finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE);127 void finalizeCGProfile();128 void createAddrSigSection();129};130 131} // end anonymous namespace.132 133void MCMachOStreamer::changeSection(MCSection *Section, uint32_t Subsection) {134 MCObjectStreamer::changeSection(Section, Subsection);135 136 // Output a linker-local symbol so we don't need section-relative local137 // relocations. The linker hates us when we do that.138 if (LabelSections && !HasSectionLabel[Section] &&139 !Section->getBeginSymbol()) {140 MCSymbol *Label = getContext().createLinkerPrivateTempSymbol();141 Section->setBeginSymbol(Label);142 HasSectionLabel[Section] = true;143 if (!Label->isInSection())144 emitLabel(Label);145 }146}147 148void MCMachOStreamer::emitEHSymAttributes(const MCSymbol *Symbol,149 MCSymbol *EHSymbol) {150 auto *Sym = static_cast<const MCSymbolMachO *>(Symbol);151 getAssembler().registerSymbol(*Symbol);152 if (Sym->isExternal())153 emitSymbolAttribute(EHSymbol, MCSA_Global);154 if (Sym->isWeakDefinition())155 emitSymbolAttribute(EHSymbol, MCSA_WeakDefinition);156 if (Sym->isPrivateExtern())157 emitSymbolAttribute(EHSymbol, MCSA_PrivateExtern);158}159 160void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {161 // We have to create a new fragment if this is an atom defining symbol,162 // fragments cannot span atoms.163 if (static_cast<MCSymbolMachO *>(Symbol)->isSymbolLinkerVisible())164 newFragment();165 166 MCObjectStreamer::emitLabel(Symbol, Loc);167 168 // This causes the reference type flag to be cleared. Darwin 'as' was "trying"169 // to clear the weak reference and weak definition bits too, but the170 // implementation was buggy. For now we just try to match 'as', for171 // diffability.172 //173 // FIXME: Cleanup this code, these bits should be emitted based on semantic174 // properties, not on the order of definition, etc.175 static_cast<MCSymbolMachO *>(Symbol)->clearReferenceType();176}177 178void MCMachOStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {179 MCValue Res;180 181 if (Value->evaluateAsRelocatable(Res, nullptr)) {182 if (const auto *SymA = Res.getAddSym()) {183 if (!Res.getSubSym() &&184 (SymA->getName().empty() || Res.getConstant() != 0))185 static_cast<MCSymbolMachO *>(Symbol)->setAltEntry();186 }187 }188 MCObjectStreamer::emitAssignment(Symbol, Value);189}190 191void MCMachOStreamer::emitDataRegion(MachO::DataRegionType Kind) {192 // Create a temporary label to mark the start of the data region.193 MCSymbol *Start = getContext().createTempSymbol();194 emitLabel(Start);195 // Record the region for the object writer to use.196 getWriter().getDataRegions().push_back({Kind, Start, nullptr});197}198 199void MCMachOStreamer::emitDataRegionEnd() {200 auto &Regions = getWriter().getDataRegions();201 assert(!Regions.empty() && "Mismatched .end_data_region!");202 auto &Data = Regions.back();203 assert(!Data.End && "Mismatched .end_data_region!");204 // Create a temporary label to mark the end of the data region.205 Data.End = getContext().createTempSymbol();206 emitLabel(Data.End);207}208 209void MCMachOStreamer::emitSubsectionsViaSymbols() {210 getWriter().setSubsectionsViaSymbols(true);211}212 213void MCMachOStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {214 getWriter().getLinkerOptions().push_back(Options);215}216 217void MCMachOStreamer::emitDataRegion(MCDataRegionType Kind) {218 switch (Kind) {219 case MCDR_DataRegion:220 emitDataRegion(MachO::DataRegionType::DICE_KIND_DATA);221 return;222 case MCDR_DataRegionJT8:223 emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE8);224 return;225 case MCDR_DataRegionJT16:226 emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE16);227 return;228 case MCDR_DataRegionJT32:229 emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE32);230 return;231 case MCDR_DataRegionEnd:232 emitDataRegionEnd();233 return;234 }235}236 237void MCMachOStreamer::emitVersionMin(MCVersionMinType Kind, unsigned Major,238 unsigned Minor, unsigned Update,239 VersionTuple SDKVersion) {240 getWriter().setVersionMin(Kind, Major, Minor, Update, SDKVersion);241}242 243void MCMachOStreamer::emitBuildVersion(unsigned Platform, unsigned Major,244 unsigned Minor, unsigned Update,245 VersionTuple SDKVersion) {246 getWriter().setBuildVersion((MachO::PlatformType)Platform, Major, Minor,247 Update, SDKVersion);248}249 250void MCMachOStreamer::emitDarwinTargetVariantBuildVersion(251 unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,252 VersionTuple SDKVersion) {253 getWriter().setTargetVariantBuildVersion((MachO::PlatformType)Platform, Major,254 Minor, Update, SDKVersion);255}256 257bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,258 MCSymbolAttr Attribute) {259 auto *Symbol = static_cast<MCSymbolMachO *>(Sym);260 261 // Indirect symbols are handled differently, to match how 'as' handles262 // them. This makes writing matching .o files easier.263 if (Attribute == MCSA_IndirectSymbol) {264 // Note that we intentionally cannot use the symbol data here; this is265 // important for matching the string table that 'as' generates.266 getWriter().getIndirectSymbols().push_back(267 {Symbol, getCurrentSectionOnly()});268 return true;269 }270 271 // Adding a symbol attribute always introduces the symbol, note that an272 // important side effect of calling registerSymbol here is to register273 // the symbol with the assembler.274 getAssembler().registerSymbol(*Symbol);275 276 // The implementation of symbol attributes is designed to match 'as', but it277 // leaves much to desired. It doesn't really make sense to arbitrarily add and278 // remove flags, but 'as' allows this (in particular, see .desc).279 //280 // In the future it might be worth trying to make these operations more well281 // defined.282 switch (Attribute) {283 case MCSA_Invalid:284 case MCSA_ELF_TypeFunction:285 case MCSA_ELF_TypeIndFunction:286 case MCSA_ELF_TypeObject:287 case MCSA_ELF_TypeTLS:288 case MCSA_ELF_TypeCommon:289 case MCSA_ELF_TypeNoType:290 case MCSA_ELF_TypeGnuUniqueObject:291 case MCSA_Extern:292 case MCSA_Hidden:293 case MCSA_IndirectSymbol:294 case MCSA_Internal:295 case MCSA_Protected:296 case MCSA_Weak:297 case MCSA_Local:298 case MCSA_LGlobal:299 case MCSA_Exported:300 case MCSA_Memtag:301 case MCSA_WeakAntiDep:302 return false;303 304 case MCSA_Global:305 Symbol->setExternal(true);306 // This effectively clears the undefined lazy bit, in Darwin 'as', although307 // it isn't very consistent because it implements this as part of symbol308 // lookup.309 //310 // FIXME: Cleanup this code, these bits should be emitted based on semantic311 // properties, not on the order of definition, etc.312 Symbol->setReferenceTypeUndefinedLazy(false);313 break;314 315 case MCSA_LazyReference:316 // FIXME: This requires -dynamic.317 Symbol->setNoDeadStrip();318 if (Symbol->isUndefined())319 Symbol->setReferenceTypeUndefinedLazy(true);320 break;321 322 // Since .reference sets the no dead strip bit, it is equivalent to323 // .no_dead_strip in practice.324 case MCSA_Reference:325 case MCSA_NoDeadStrip:326 Symbol->setNoDeadStrip();327 break;328 329 case MCSA_SymbolResolver:330 Symbol->setSymbolResolver();331 break;332 333 case MCSA_AltEntry:334 Symbol->setAltEntry();335 break;336 337 case MCSA_PrivateExtern:338 Symbol->setExternal(true);339 Symbol->setPrivateExtern(true);340 break;341 342 case MCSA_WeakReference:343 // FIXME: This requires -dynamic.344 if (Symbol->isUndefined())345 Symbol->setWeakReference();346 break;347 348 case MCSA_WeakDefinition:349 // FIXME: 'as' enforces that this is defined and global. The manual claims350 // it has to be in a coalesced section, but this isn't enforced.351 Symbol->setWeakDefinition();352 break;353 354 case MCSA_WeakDefAutoPrivate:355 Symbol->setWeakDefinition();356 Symbol->setWeakReference();357 break;358 359 case MCSA_Cold:360 Symbol->setCold();361 break;362 }363 364 return true;365}366 367void MCMachOStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {368 // Encode the 'desc' value into the lowest implementation defined bits.369 getAssembler().registerSymbol(*Symbol);370 static_cast<MCSymbolMachO *>(Symbol)->setDesc(DescValue);371}372 373void MCMachOStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,374 Align ByteAlignment) {375 auto &Sym = static_cast<MCSymbolMachO &>(*Symbol);376 // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.377 assert(Symbol->isUndefined() && "Cannot define a symbol twice!");378 379 getAssembler().registerSymbol(Sym);380 Sym.setExternal(true);381 Sym.setCommon(Size, ByteAlignment);382}383 384void MCMachOStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,385 Align ByteAlignment) {386 // '.lcomm' is equivalent to '.zerofill'.387 return emitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(),388 Symbol, Size, ByteAlignment);389}390 391void MCMachOStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,392 uint64_t Size, Align ByteAlignment,393 SMLoc Loc) {394 // On darwin all virtual sections have zerofill type. Disallow the usage of395 // .zerofill in non-virtual functions. If something similar is needed, use396 // .space or .zero.397 if (!Section->isBssSection()) {398 getContext().reportError(399 Loc, "The usage of .zerofill is restricted to sections of "400 "ZEROFILL type. Use .zero or .space instead.");401 return; // Early returning here shouldn't harm. EmitZeros should work on any402 // section.403 }404 405 pushSection();406 switchSection(Section);407 408 // The symbol may not be present, which only creates the section.409 if (Symbol) {410 emitValueToAlignment(ByteAlignment, 0, 1, 0);411 emitLabel(Symbol);412 emitZeros(Size);413 }414 popSection();415}416 417// This should always be called with the thread local bss section. Like the418// .zerofill directive this doesn't actually switch sections on us.419void MCMachOStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,420 uint64_t Size, Align ByteAlignment) {421 emitZerofill(Section, Symbol, Size, ByteAlignment);422}423 424void MCMachOStreamer::finishImpl() {425 emitFrames();426 427 // We have to set the fragment atom associations so we can relax properly for428 // Mach-O.429 430 // First, scan the symbol table to build a lookup table from fragments to431 // defining symbols.432 DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;433 for (const MCSymbol &Symbol : getAssembler().symbols()) {434 auto &Sym = static_cast<const MCSymbolMachO &>(Symbol);435 if (Sym.isSymbolLinkerVisible() && Sym.isInSection() && !Sym.isVariable() &&436 !Sym.isAltEntry()) {437 // An atom defining symbol should never be internal to a fragment.438 assert(Symbol.getOffset() == 0 &&439 "Invalid offset in atom defining symbol!");440 DefiningSymbolMap[Symbol.getFragment()] = &Symbol;441 }442 }443 444 // Set the fragment atom associations by tracking the last seen atom defining445 // symbol.446 for (MCSection &Sec : getAssembler()) {447 static_cast<MCSectionMachO &>(Sec).allocAtoms();448 const MCSymbol *CurrentAtom = nullptr;449 size_t I = 0;450 for (MCFragment &Frag : Sec) {451 if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag))452 CurrentAtom = Symbol;453 static_cast<MCSectionMachO &>(Sec).setAtom(I++, CurrentAtom);454 }455 }456 457 finalizeCGProfile();458 459 createAddrSigSection();460 this->MCObjectStreamer::finishImpl();461}462 463void MCMachOStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {464 auto *S =465 static_cast<MCSymbolMachO *>(const_cast<MCSymbol *>(&SRE->getSymbol()));466 if (getAssembler().registerSymbol(*S))467 S->setExternal(true);468}469 470void MCMachOStreamer::finalizeCGProfile() {471 MCAssembler &Asm = getAssembler();472 MCObjectWriter &W = getWriter();473 if (W.getCGProfile().empty())474 return;475 for (auto &E : W.getCGProfile()) {476 finalizeCGProfileEntry(E.From);477 finalizeCGProfileEntry(E.To);478 }479 // We can't write the section out until symbol indices are finalized which480 // doesn't happen until after section layout. We need to create the section481 // and set its size now so that it's accounted for in layout.482 MCSection *CGProfileSection = Asm.getContext().getMachOSection(483 "__LLVM", "__cg_profile", 0, SectionKind::getMetadata());484 // Call the base class changeSection to omit the linker-local label.485 MCObjectStreamer::changeSection(CGProfileSection);486 // For each entry, reserve space for 2 32-bit indices and a 64-bit count.487 size_t SectionBytes =488 W.getCGProfile().size() * (2 * sizeof(uint32_t) + sizeof(uint64_t));489 (*CGProfileSection->begin())490 .setVarContents(std::vector<char>(SectionBytes, 0));491}492 493MCStreamer *llvm::createMachOStreamer(MCContext &Context,494 std::unique_ptr<MCAsmBackend> &&MAB,495 std::unique_ptr<MCObjectWriter> &&OW,496 std::unique_ptr<MCCodeEmitter> &&CE,497 bool DWARFMustBeAtTheEnd,498 bool LabelSections) {499 return new MCMachOStreamer(Context, std::move(MAB), std::move(OW),500 std::move(CE), LabelSections);501}502 503// The AddrSig section uses a series of relocations to refer to the symbols that504// should be considered address-significant. The only interesting content of505// these relocations is their symbol; the type, length etc will be ignored by506// the linker. The reason we are not referring to the symbol indices directly is507// that those indices will be invalidated by tools that update the symbol table.508// Symbol relocations OTOH will have their indices updated by e.g. llvm-strip.509void MCMachOStreamer::createAddrSigSection() {510 MCAssembler &Asm = getAssembler();511 MCObjectWriter &writer = Asm.getWriter();512 if (!writer.getEmitAddrsigSection())513 return;514 // Create the AddrSig section and first data fragment here as its layout needs515 // to be computed immediately after in order for it to be exported correctly.516 MCSection *AddrSigSection =517 Asm.getContext().getObjectFileInfo()->getAddrSigSection();518 // Call the base class changeSection to omit the linker-local label.519 MCObjectStreamer::changeSection(AddrSigSection);520 auto *Frag = cast<MCFragment>(AddrSigSection->curFragList()->Head);521 // We will generate a series of pointer-sized symbol relocations at offset522 // 0x0. Set the section size to be large enough to contain a single pointer523 // (instead of emitting a zero-sized section) so these relocations are524 // technically valid, even though we don't expect these relocations to525 // actually be applied by the linker.526 constexpr char zero[8] = {};527 Frag->setVarContents(zero);528}529