Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCMachOStreamer.cpp
35233 views
//===- MCMachOStreamer.cpp - MachO Streamer -------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ADT/DenseMap.h"9#include "llvm/ADT/SmallString.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/MCFragment.h"21#include "llvm/MC/MCLinkerOptimizationHint.h"22#include "llvm/MC/MCMachObjectWriter.h"23#include "llvm/MC/MCObjectFileInfo.h"24#include "llvm/MC/MCObjectStreamer.h"25#include "llvm/MC/MCObjectWriter.h"26#include "llvm/MC/MCSection.h"27#include "llvm/MC/MCSectionMachO.h"28#include "llvm/MC/MCSymbol.h"29#include "llvm/MC/MCSymbolMachO.h"30#include "llvm/MC/MCValue.h"31#include "llvm/MC/SectionKind.h"32#include "llvm/MC/TargetRegistry.h"33#include "llvm/Support/Casting.h"34#include "llvm/Support/ErrorHandling.h"35#include <cassert>36#include <vector>3738namespace llvm {39class MCInst;40class MCStreamer;41class MCSubtargetInfo;42class Triple;43} // namespace llvm4445using namespace llvm;4647namespace {4849class MCMachOStreamer : public MCObjectStreamer {50private:51/// LabelSections - true if each section change should emit a linker local52/// label for use in relocations for assembler local references. Obviates the53/// need for local relocations. False by default.54bool LabelSections;5556/// HasSectionLabel - map of which sections have already had a non-local57/// label emitted to them. Used so we don't emit extraneous linker local58/// labels in the middle of the section.59DenseMap<const MCSection*, bool> HasSectionLabel;6061void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;6263void emitDataRegion(MachO::DataRegionType Kind);64void emitDataRegionEnd();6566public:67MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,68std::unique_ptr<MCObjectWriter> OW,69std::unique_ptr<MCCodeEmitter> Emitter, bool label)70: MCObjectStreamer(Context, std::move(MAB), std::move(OW),71std::move(Emitter)),72LabelSections(label) {}7374/// state management75void reset() override {76HasSectionLabel.clear();77MCObjectStreamer::reset();78}7980MachObjectWriter &getWriter() {81return static_cast<MachObjectWriter &>(getAssembler().getWriter());82}8384/// @name MCStreamer Interface85/// @{8687void changeSection(MCSection *Sect, uint32_t Subsection = 0) override;88void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;89void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;90void emitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;91void emitAssemblerFlag(MCAssemblerFlag Flag) override;92void emitLinkerOptions(ArrayRef<std::string> Options) override;93void emitDataRegion(MCDataRegionType Kind) override;94void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,95unsigned Update, VersionTuple SDKVersion) override;96void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,97unsigned Update, VersionTuple SDKVersion) override;98void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,99unsigned Minor, unsigned Update,100VersionTuple SDKVersion) override;101void emitThumbFunc(MCSymbol *Func) override;102bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;103void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;104void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,105Align ByteAlignment) override;106107void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,108Align ByteAlignment) override;109void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,110uint64_t Size = 0, Align ByteAlignment = Align(1),111SMLoc Loc = SMLoc()) override;112void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,113Align ByteAlignment = Align(1)) override;114115void emitIdent(StringRef IdentString) override {116llvm_unreachable("macho doesn't support this directive");117}118119void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {120getWriter().getLOHContainer().addDirective(Kind, Args);121}122void emitCGProfileEntry(const MCSymbolRefExpr *From,123const MCSymbolRefExpr *To, uint64_t Count) override {124if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())125getWriter().getCGProfile().push_back({From, To, Count});126}127128void finishImpl() override;129130void finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE);131void finalizeCGProfile();132void createAddrSigSection();133};134135} // end anonymous namespace.136137void MCMachOStreamer::changeSection(MCSection *Section, uint32_t Subsection) {138// Change the section normally.139changeSectionImpl(Section, Subsection);140141// Output a linker-local symbol so we don't need section-relative local142// relocations. The linker hates us when we do that.143if (LabelSections && !HasSectionLabel[Section] &&144!Section->getBeginSymbol()) {145MCSymbol *Label = getContext().createLinkerPrivateTempSymbol();146Section->setBeginSymbol(Label);147HasSectionLabel[Section] = true;148}149}150151void MCMachOStreamer::emitEHSymAttributes(const MCSymbol *Symbol,152MCSymbol *EHSymbol) {153auto *Sym = cast<MCSymbolMachO>(Symbol);154getAssembler().registerSymbol(*Symbol);155if (Symbol->isExternal())156emitSymbolAttribute(EHSymbol, MCSA_Global);157if (Sym->isWeakDefinition())158emitSymbolAttribute(EHSymbol, MCSA_WeakDefinition);159if (Sym->isPrivateExtern())160emitSymbolAttribute(EHSymbol, MCSA_PrivateExtern);161}162163void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {164// We have to create a new fragment if this is an atom defining symbol,165// fragments cannot span atoms.166if (cast<MCSymbolMachO>(Symbol)->isSymbolLinkerVisible())167insert(getContext().allocFragment<MCDataFragment>());168169MCObjectStreamer::emitLabel(Symbol, Loc);170171// This causes the reference type flag to be cleared. Darwin 'as' was "trying"172// to clear the weak reference and weak definition bits too, but the173// implementation was buggy. For now we just try to match 'as', for174// diffability.175//176// FIXME: Cleanup this code, these bits should be emitted based on semantic177// properties, not on the order of definition, etc.178cast<MCSymbolMachO>(Symbol)->clearReferenceType();179}180181void MCMachOStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {182MCValue Res;183184if (Value->evaluateAsRelocatable(Res, nullptr, nullptr)) {185if (const MCSymbolRefExpr *SymAExpr = Res.getSymA()) {186const MCSymbol &SymA = SymAExpr->getSymbol();187if (!Res.getSymB() && (SymA.getName() == "" || Res.getConstant() != 0))188cast<MCSymbolMachO>(Symbol)->setAltEntry();189}190}191MCObjectStreamer::emitAssignment(Symbol, Value);192}193194void MCMachOStreamer::emitDataRegion(MachO::DataRegionType Kind) {195// Create a temporary label to mark the start of the data region.196MCSymbol *Start = getContext().createTempSymbol();197emitLabel(Start);198// Record the region for the object writer to use.199getWriter().getDataRegions().push_back({Kind, Start, nullptr});200}201202void MCMachOStreamer::emitDataRegionEnd() {203auto &Regions = getWriter().getDataRegions();204assert(!Regions.empty() && "Mismatched .end_data_region!");205auto &Data = Regions.back();206assert(!Data.End && "Mismatched .end_data_region!");207// Create a temporary label to mark the end of the data region.208Data.End = getContext().createTempSymbol();209emitLabel(Data.End);210}211212void MCMachOStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {213// Let the target do whatever target specific stuff it needs to do.214getAssembler().getBackend().handleAssemblerFlag(Flag);215// Do any generic stuff we need to do.216switch (Flag) {217case MCAF_SyntaxUnified: return; // no-op here.218case MCAF_Code16: return; // Change parsing mode; no-op here.219case MCAF_Code32: return; // Change parsing mode; no-op here.220case MCAF_Code64: return; // Change parsing mode; no-op here.221case MCAF_SubsectionsViaSymbols:222getWriter().setSubsectionsViaSymbols(true);223return;224}225}226227void MCMachOStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {228getWriter().getLinkerOptions().push_back(Options);229}230231void MCMachOStreamer::emitDataRegion(MCDataRegionType Kind) {232switch (Kind) {233case MCDR_DataRegion:234emitDataRegion(MachO::DataRegionType::DICE_KIND_DATA);235return;236case MCDR_DataRegionJT8:237emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE8);238return;239case MCDR_DataRegionJT16:240emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE16);241return;242case MCDR_DataRegionJT32:243emitDataRegion(MachO::DataRegionType::DICE_KIND_JUMP_TABLE32);244return;245case MCDR_DataRegionEnd:246emitDataRegionEnd();247return;248}249}250251void MCMachOStreamer::emitVersionMin(MCVersionMinType Kind, unsigned Major,252unsigned Minor, unsigned Update,253VersionTuple SDKVersion) {254getWriter().setVersionMin(Kind, Major, Minor, Update, SDKVersion);255}256257void MCMachOStreamer::emitBuildVersion(unsigned Platform, unsigned Major,258unsigned Minor, unsigned Update,259VersionTuple SDKVersion) {260getWriter().setBuildVersion((MachO::PlatformType)Platform, Major, Minor,261Update, SDKVersion);262}263264void MCMachOStreamer::emitDarwinTargetVariantBuildVersion(265unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,266VersionTuple SDKVersion) {267getWriter().setTargetVariantBuildVersion((MachO::PlatformType)Platform, Major,268Minor, Update, SDKVersion);269}270271void MCMachOStreamer::emitThumbFunc(MCSymbol *Symbol) {272// Remember that the function is a thumb function. Fixup and relocation273// values will need adjusted.274getAssembler().setIsThumbFunc(Symbol);275cast<MCSymbolMachO>(Symbol)->setThumbFunc();276}277278bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,279MCSymbolAttr Attribute) {280MCSymbolMachO *Symbol = cast<MCSymbolMachO>(Sym);281282// Indirect symbols are handled differently, to match how 'as' handles283// them. This makes writing matching .o files easier.284if (Attribute == MCSA_IndirectSymbol) {285// Note that we intentionally cannot use the symbol data here; this is286// important for matching the string table that 'as' generates.287getWriter().getIndirectSymbols().push_back(288{Symbol, getCurrentSectionOnly()});289return true;290}291292// Adding a symbol attribute always introduces the symbol, note that an293// important side effect of calling registerSymbol here is to register294// the symbol with the assembler.295getAssembler().registerSymbol(*Symbol);296297// The implementation of symbol attributes is designed to match 'as', but it298// leaves much to desired. It doesn't really make sense to arbitrarily add and299// remove flags, but 'as' allows this (in particular, see .desc).300//301// In the future it might be worth trying to make these operations more well302// defined.303switch (Attribute) {304case MCSA_Invalid:305case MCSA_ELF_TypeFunction:306case MCSA_ELF_TypeIndFunction:307case MCSA_ELF_TypeObject:308case MCSA_ELF_TypeTLS:309case MCSA_ELF_TypeCommon:310case MCSA_ELF_TypeNoType:311case MCSA_ELF_TypeGnuUniqueObject:312case MCSA_Extern:313case MCSA_Hidden:314case MCSA_IndirectSymbol:315case MCSA_Internal:316case MCSA_Protected:317case MCSA_Weak:318case MCSA_Local:319case MCSA_LGlobal:320case MCSA_Exported:321case MCSA_Memtag:322case MCSA_WeakAntiDep:323return false;324325case MCSA_Global:326Symbol->setExternal(true);327// This effectively clears the undefined lazy bit, in Darwin 'as', although328// it isn't very consistent because it implements this as part of symbol329// lookup.330//331// FIXME: Cleanup this code, these bits should be emitted based on semantic332// properties, not on the order of definition, etc.333Symbol->setReferenceTypeUndefinedLazy(false);334break;335336case MCSA_LazyReference:337// FIXME: This requires -dynamic.338Symbol->setNoDeadStrip();339if (Symbol->isUndefined())340Symbol->setReferenceTypeUndefinedLazy(true);341break;342343// Since .reference sets the no dead strip bit, it is equivalent to344// .no_dead_strip in practice.345case MCSA_Reference:346case MCSA_NoDeadStrip:347Symbol->setNoDeadStrip();348break;349350case MCSA_SymbolResolver:351Symbol->setSymbolResolver();352break;353354case MCSA_AltEntry:355Symbol->setAltEntry();356break;357358case MCSA_PrivateExtern:359Symbol->setExternal(true);360Symbol->setPrivateExtern(true);361break;362363case MCSA_WeakReference:364// FIXME: This requires -dynamic.365if (Symbol->isUndefined())366Symbol->setWeakReference();367break;368369case MCSA_WeakDefinition:370// FIXME: 'as' enforces that this is defined and global. The manual claims371// it has to be in a coalesced section, but this isn't enforced.372Symbol->setWeakDefinition();373break;374375case MCSA_WeakDefAutoPrivate:376Symbol->setWeakDefinition();377Symbol->setWeakReference();378break;379380case MCSA_Cold:381Symbol->setCold();382break;383}384385return true;386}387388void MCMachOStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {389// Encode the 'desc' value into the lowest implementation defined bits.390getAssembler().registerSymbol(*Symbol);391cast<MCSymbolMachO>(Symbol)->setDesc(DescValue);392}393394void MCMachOStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,395Align ByteAlignment) {396// FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.397assert(Symbol->isUndefined() && "Cannot define a symbol twice!");398399getAssembler().registerSymbol(*Symbol);400Symbol->setExternal(true);401Symbol->setCommon(Size, ByteAlignment);402}403404void MCMachOStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,405Align ByteAlignment) {406// '.lcomm' is equivalent to '.zerofill'.407return emitZerofill(getContext().getObjectFileInfo()->getDataBSSSection(),408Symbol, Size, ByteAlignment);409}410411void MCMachOStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,412uint64_t Size, Align ByteAlignment,413SMLoc Loc) {414// On darwin all virtual sections have zerofill type. Disallow the usage of415// .zerofill in non-virtual functions. If something similar is needed, use416// .space or .zero.417if (!Section->isVirtualSection()) {418getContext().reportError(419Loc, "The usage of .zerofill is restricted to sections of "420"ZEROFILL type. Use .zero or .space instead.");421return; // Early returning here shouldn't harm. EmitZeros should work on any422// section.423}424425pushSection();426switchSection(Section);427428// The symbol may not be present, which only creates the section.429if (Symbol) {430emitValueToAlignment(ByteAlignment, 0, 1, 0);431emitLabel(Symbol);432emitZeros(Size);433}434popSection();435}436437// This should always be called with the thread local bss section. Like the438// .zerofill directive this doesn't actually switch sections on us.439void MCMachOStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,440uint64_t Size, Align ByteAlignment) {441emitZerofill(Section, Symbol, Size, ByteAlignment);442}443444void MCMachOStreamer::emitInstToData(const MCInst &Inst,445const MCSubtargetInfo &STI) {446MCDataFragment *DF = getOrCreateDataFragment();447448SmallVector<MCFixup, 4> Fixups;449SmallString<256> Code;450getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);451452// Add the fixups and data.453for (MCFixup &Fixup : Fixups) {454Fixup.setOffset(Fixup.getOffset() + DF->getContents().size());455DF->getFixups().push_back(Fixup);456}457DF->setHasInstructions(STI);458DF->getContents().append(Code.begin(), Code.end());459}460461void MCMachOStreamer::finishImpl() {462emitFrames(&getAssembler().getBackend());463464// We have to set the fragment atom associations so we can relax properly for465// Mach-O.466467// First, scan the symbol table to build a lookup table from fragments to468// defining symbols.469DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;470for (const MCSymbol &Symbol : getAssembler().symbols()) {471auto &Sym = cast<MCSymbolMachO>(Symbol);472if (Sym.isSymbolLinkerVisible() && Sym.isInSection() && !Sym.isVariable() &&473!Sym.isAltEntry()) {474// An atom defining symbol should never be internal to a fragment.475assert(Symbol.getOffset() == 0 &&476"Invalid offset in atom defining symbol!");477DefiningSymbolMap[Symbol.getFragment()] = &Symbol;478}479}480481// Set the fragment atom associations by tracking the last seen atom defining482// symbol.483for (MCSection &Sec : getAssembler()) {484cast<MCSectionMachO>(Sec).allocAtoms();485const MCSymbol *CurrentAtom = nullptr;486size_t I = 0;487for (MCFragment &Frag : Sec) {488if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag))489CurrentAtom = Symbol;490cast<MCSectionMachO>(Sec).setAtom(I++, CurrentAtom);491}492}493494finalizeCGProfile();495496createAddrSigSection();497this->MCObjectStreamer::finishImpl();498}499500void MCMachOStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {501const MCSymbol *S = &SRE->getSymbol();502if (getAssembler().registerSymbol(*S))503S->setExternal(true);504}505506void MCMachOStreamer::finalizeCGProfile() {507MCAssembler &Asm = getAssembler();508MCObjectWriter &W = getWriter();509if (W.getCGProfile().empty())510return;511for (auto &E : W.getCGProfile()) {512finalizeCGProfileEntry(E.From);513finalizeCGProfileEntry(E.To);514}515// We can't write the section out until symbol indices are finalized which516// doesn't happen until after section layout. We need to create the section517// and set its size now so that it's accounted for in layout.518MCSection *CGProfileSection = Asm.getContext().getMachOSection(519"__LLVM", "__cg_profile", 0, SectionKind::getMetadata());520changeSection(CGProfileSection);521// For each entry, reserve space for 2 32-bit indices and a 64-bit count.522size_t SectionBytes =523W.getCGProfile().size() * (2 * sizeof(uint32_t) + sizeof(uint64_t));524cast<MCDataFragment>(*CGProfileSection->begin())525.getContents()526.resize(SectionBytes);527}528529MCStreamer *llvm::createMachOStreamer(MCContext &Context,530std::unique_ptr<MCAsmBackend> &&MAB,531std::unique_ptr<MCObjectWriter> &&OW,532std::unique_ptr<MCCodeEmitter> &&CE,533bool DWARFMustBeAtTheEnd,534bool LabelSections) {535MCMachOStreamer *S = new MCMachOStreamer(536Context, std::move(MAB), std::move(OW), std::move(CE), LabelSections);537const Triple &Target = Context.getTargetTriple();538S->emitVersionForTarget(539Target, Context.getObjectFileInfo()->getSDKVersion(),540Context.getObjectFileInfo()->getDarwinTargetVariantTriple(),541Context.getObjectFileInfo()->getDarwinTargetVariantSDKVersion());542return S;543}544545// The AddrSig section uses a series of relocations to refer to the symbols that546// should be considered address-significant. The only interesting content of547// these relocations is their symbol; the type, length etc will be ignored by548// the linker. The reason we are not referring to the symbol indices directly is549// that those indices will be invalidated by tools that update the symbol table.550// Symbol relocations OTOH will have their indices updated by e.g. llvm-strip.551void MCMachOStreamer::createAddrSigSection() {552MCAssembler &Asm = getAssembler();553MCObjectWriter &writer = Asm.getWriter();554if (!writer.getEmitAddrsigSection())555return;556// Create the AddrSig section and first data fragment here as its layout needs557// to be computed immediately after in order for it to be exported correctly.558MCSection *AddrSigSection =559Asm.getContext().getObjectFileInfo()->getAddrSigSection();560changeSection(AddrSigSection);561auto *Frag = cast<MCDataFragment>(AddrSigSection->curFragList()->Head);562// We will generate a series of pointer-sized symbol relocations at offset563// 0x0. Set the section size to be large enough to contain a single pointer564// (instead of emitting a zero-sized section) so these relocations are565// technically valid, even though we don't expect these relocations to566// actually be applied by the linker.567Frag->getContents().resize(8);568}569570571