brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.4 KiB · cde1d66 Raw
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