Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp
35233 views
//===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===//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//===----------------------------------------------------------------------===//7//8// This file assembles .s files and emits ELF .o object files.9//10//===----------------------------------------------------------------------===//1112#include "llvm/MC/MCELFStreamer.h"13#include "llvm/ADT/SmallString.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/BinaryFormat/ELF.h"16#include "llvm/MC/MCAsmBackend.h"17#include "llvm/MC/MCAsmInfo.h"18#include "llvm/MC/MCAssembler.h"19#include "llvm/MC/MCCodeEmitter.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCExpr.h"22#include "llvm/MC/MCFixup.h"23#include "llvm/MC/MCFragment.h"24#include "llvm/MC/MCObjectFileInfo.h"25#include "llvm/MC/MCObjectWriter.h"26#include "llvm/MC/MCSection.h"27#include "llvm/MC/MCSectionELF.h"28#include "llvm/MC/MCStreamer.h"29#include "llvm/MC/MCSymbol.h"30#include "llvm/MC/MCSymbolELF.h"31#include "llvm/MC/TargetRegistry.h"32#include "llvm/Support/Casting.h"33#include "llvm/Support/ErrorHandling.h"34#include "llvm/Support/LEB128.h"35#include "llvm/Support/raw_ostream.h"36#include <cassert>37#include <cstdint>3839using namespace llvm;4041MCELFStreamer::MCELFStreamer(MCContext &Context,42std::unique_ptr<MCAsmBackend> TAB,43std::unique_ptr<MCObjectWriter> OW,44std::unique_ptr<MCCodeEmitter> Emitter)45: MCObjectStreamer(Context, std::move(TAB), std::move(OW),46std::move(Emitter)) {}4748ELFObjectWriter &MCELFStreamer::getWriter() {49return static_cast<ELFObjectWriter &>(getAssembler().getWriter());50}5152bool MCELFStreamer::isBundleLocked() const {53return getCurrentSectionOnly()->isBundleLocked();54}5556void MCELFStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) {57MCContext &Ctx = getContext();58switchSection(Ctx.getObjectFileInfo()->getTextSection());59emitCodeAlignment(Align(Ctx.getObjectFileInfo()->getTextSectionAlignment()),60&STI);6162if (NoExecStack)63switchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));64}6566void MCELFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {67auto *Symbol = cast<MCSymbolELF>(S);68MCObjectStreamer::emitLabel(Symbol, Loc);6970const MCSectionELF &Section =71static_cast<const MCSectionELF &>(*getCurrentSectionOnly());72if (Section.getFlags() & ELF::SHF_TLS)73Symbol->setType(ELF::STT_TLS);74}7576void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F,77uint64_t Offset) {78auto *Symbol = cast<MCSymbolELF>(S);79MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset);8081const MCSectionELF &Section =82static_cast<const MCSectionELF &>(*getCurrentSectionOnly());83if (Section.getFlags() & ELF::SHF_TLS)84Symbol->setType(ELF::STT_TLS);85}8687void MCELFStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {88// Let the target do whatever target specific stuff it needs to do.89getAssembler().getBackend().handleAssemblerFlag(Flag);90}9192// If bundle alignment is used and there are any instructions in the section, it93// needs to be aligned to at least the bundle size.94static void setSectionAlignmentForBundling(const MCAssembler &Assembler,95MCSection *Section) {96if (Assembler.isBundlingEnabled() && Section->hasInstructions())97Section->ensureMinAlignment(Align(Assembler.getBundleAlignSize()));98}99100void MCELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {101MCAssembler &Asm = getAssembler();102if (auto *F = getCurrentFragment()) {103if (isBundleLocked())104report_fatal_error("Unterminated .bundle_lock when changing a section");105106// Ensure the previous section gets aligned if necessary.107setSectionAlignmentForBundling(Asm, F->getParent());108}109auto *SectionELF = static_cast<const MCSectionELF *>(Section);110const MCSymbol *Grp = SectionELF->getGroup();111if (Grp)112Asm.registerSymbol(*Grp);113if (SectionELF->getFlags() & ELF::SHF_GNU_RETAIN)114getWriter().markGnuAbi();115116changeSectionImpl(Section, Subsection);117Asm.registerSymbol(*Section->getBeginSymbol());118}119120void MCELFStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {121getAssembler().registerSymbol(*Symbol);122const MCExpr *Value = MCSymbolRefExpr::create(123Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());124Alias->setVariableValue(Value);125}126127// When GNU as encounters more than one .type declaration for an object it seems128// to use a mechanism similar to the one below to decide which type is actually129// used in the object file. The greater of T1 and T2 is selected based on the130// following ordering:131// STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else132// If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user133// provided type).134static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) {135for (unsigned Type : {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC,136ELF::STT_GNU_IFUNC, ELF::STT_TLS}) {137if (T1 == Type)138return T2;139if (T2 == Type)140return T1;141}142143return T2;144}145146bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {147auto *Symbol = cast<MCSymbolELF>(S);148149// Adding a symbol attribute always introduces the symbol, note that an150// important side effect of calling registerSymbol here is to register151// the symbol with the assembler.152getAssembler().registerSymbol(*Symbol);153154// The implementation of symbol attributes is designed to match 'as', but it155// leaves much to desired. It doesn't really make sense to arbitrarily add and156// remove flags, but 'as' allows this (in particular, see .desc).157//158// In the future it might be worth trying to make these operations more well159// defined.160switch (Attribute) {161case MCSA_Cold:162case MCSA_Extern:163case MCSA_LazyReference:164case MCSA_Reference:165case MCSA_SymbolResolver:166case MCSA_PrivateExtern:167case MCSA_WeakDefinition:168case MCSA_WeakDefAutoPrivate:169case MCSA_Invalid:170case MCSA_IndirectSymbol:171case MCSA_Exported:172case MCSA_WeakAntiDep:173return false;174175case MCSA_NoDeadStrip:176// Ignore for now.177break;178179case MCSA_ELF_TypeGnuUniqueObject:180Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));181Symbol->setBinding(ELF::STB_GNU_UNIQUE);182getWriter().markGnuAbi();183break;184185case MCSA_Global:186// For `.weak x; .global x`, GNU as sets the binding to STB_WEAK while we187// traditionally set the binding to STB_GLOBAL. This is error-prone, so we188// error on such cases. Note, we also disallow changed binding from .local.189if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_GLOBAL)190getContext().reportError(getStartTokLoc(),191Symbol->getName() +192" changed binding to STB_GLOBAL");193Symbol->setBinding(ELF::STB_GLOBAL);194break;195196case MCSA_WeakReference:197case MCSA_Weak:198// For `.global x; .weak x`, both MC and GNU as set the binding to STB_WEAK.199// We emit a warning for now but may switch to an error in the future.200if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_WEAK)201getContext().reportWarning(202getStartTokLoc(), Symbol->getName() + " changed binding to STB_WEAK");203Symbol->setBinding(ELF::STB_WEAK);204break;205206case MCSA_Local:207if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_LOCAL)208getContext().reportError(getStartTokLoc(),209Symbol->getName() +210" changed binding to STB_LOCAL");211Symbol->setBinding(ELF::STB_LOCAL);212break;213214case MCSA_ELF_TypeFunction:215Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_FUNC));216break;217218case MCSA_ELF_TypeIndFunction:219Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_GNU_IFUNC));220getWriter().markGnuAbi();221break;222223case MCSA_ELF_TypeObject:224Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));225break;226227case MCSA_ELF_TypeTLS:228Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_TLS));229break;230231case MCSA_ELF_TypeCommon:232// TODO: Emit these as a common symbol.233Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));234break;235236case MCSA_ELF_TypeNoType:237Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_NOTYPE));238break;239240case MCSA_Protected:241Symbol->setVisibility(ELF::STV_PROTECTED);242break;243244case MCSA_Memtag:245Symbol->setMemtag(true);246break;247248case MCSA_Hidden:249Symbol->setVisibility(ELF::STV_HIDDEN);250break;251252case MCSA_Internal:253Symbol->setVisibility(ELF::STV_INTERNAL);254break;255256case MCSA_AltEntry:257llvm_unreachable("ELF doesn't support the .alt_entry attribute");258259case MCSA_LGlobal:260llvm_unreachable("ELF doesn't support the .lglobl attribute");261}262263return true;264}265266void MCELFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,267Align ByteAlignment) {268auto *Symbol = cast<MCSymbolELF>(S);269getAssembler().registerSymbol(*Symbol);270271if (!Symbol->isBindingSet())272Symbol->setBinding(ELF::STB_GLOBAL);273274Symbol->setType(ELF::STT_OBJECT);275276if (Symbol->getBinding() == ELF::STB_LOCAL) {277MCSection &Section = *getAssembler().getContext().getELFSection(278".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);279MCSectionSubPair P = getCurrentSection();280switchSection(&Section);281282emitValueToAlignment(ByteAlignment, 0, 1, 0);283emitLabel(Symbol);284emitZeros(Size);285286switchSection(P.first, P.second);287} else {288if (Symbol->declareCommon(Size, ByteAlignment))289report_fatal_error(Twine("Symbol: ") + Symbol->getName() +290" redeclared as different type");291}292293cast<MCSymbolELF>(Symbol)294->setSize(MCConstantExpr::create(Size, getContext()));295}296297void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {298cast<MCSymbolELF>(Symbol)->setSize(Value);299}300301void MCELFStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,302StringRef Name,303bool KeepOriginalSym) {304getWriter().Symvers.push_back(ELFObjectWriter::Symver{305getStartTokLoc(), OriginalSym, Name, KeepOriginalSym});306}307308void MCELFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,309Align ByteAlignment) {310auto *Symbol = cast<MCSymbolELF>(S);311// FIXME: Should this be caught and done earlier?312getAssembler().registerSymbol(*Symbol);313Symbol->setBinding(ELF::STB_LOCAL);314emitCommonSymbol(Symbol, Size, ByteAlignment);315}316317void MCELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,318SMLoc Loc) {319if (isBundleLocked())320report_fatal_error("Emitting values inside a locked bundle is forbidden");321fixSymbolsInTLSFixups(Value);322MCObjectStreamer::emitValueImpl(Value, Size, Loc);323}324325void MCELFStreamer::emitValueToAlignment(Align Alignment, int64_t Value,326unsigned ValueSize,327unsigned MaxBytesToEmit) {328if (isBundleLocked())329report_fatal_error("Emitting values inside a locked bundle is forbidden");330MCObjectStreamer::emitValueToAlignment(Alignment, Value, ValueSize,331MaxBytesToEmit);332}333334void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,335const MCSymbolRefExpr *To,336uint64_t Count) {337getWriter().getCGProfile().push_back({From, To, Count});338}339340void MCELFStreamer::emitIdent(StringRef IdentString) {341MCSection *Comment = getAssembler().getContext().getELFSection(342".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1);343pushSection();344switchSection(Comment);345if (!SeenIdent) {346emitInt8(0);347SeenIdent = true;348}349emitBytes(IdentString);350emitInt8(0);351popSection();352}353354void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {355switch (expr->getKind()) {356case MCExpr::Target:357cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler());358break;359case MCExpr::Constant:360break;361362case MCExpr::Binary: {363const MCBinaryExpr *be = cast<MCBinaryExpr>(expr);364fixSymbolsInTLSFixups(be->getLHS());365fixSymbolsInTLSFixups(be->getRHS());366break;367}368369case MCExpr::SymbolRef: {370const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);371switch (symRef.getKind()) {372default:373return;374case MCSymbolRefExpr::VK_GOTTPOFF:375case MCSymbolRefExpr::VK_INDNTPOFF:376case MCSymbolRefExpr::VK_NTPOFF:377case MCSymbolRefExpr::VK_GOTNTPOFF:378case MCSymbolRefExpr::VK_TLSCALL:379case MCSymbolRefExpr::VK_TLSDESC:380case MCSymbolRefExpr::VK_TLSGD:381case MCSymbolRefExpr::VK_TLSLD:382case MCSymbolRefExpr::VK_TLSLDM:383case MCSymbolRefExpr::VK_TPOFF:384case MCSymbolRefExpr::VK_TPREL:385case MCSymbolRefExpr::VK_DTPOFF:386case MCSymbolRefExpr::VK_DTPREL:387case MCSymbolRefExpr::VK_PPC_DTPMOD:388case MCSymbolRefExpr::VK_PPC_TPREL_LO:389case MCSymbolRefExpr::VK_PPC_TPREL_HI:390case MCSymbolRefExpr::VK_PPC_TPREL_HA:391case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:392case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:393case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:394case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:395case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:396case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:397case MCSymbolRefExpr::VK_PPC_DTPREL_LO:398case MCSymbolRefExpr::VK_PPC_DTPREL_HI:399case MCSymbolRefExpr::VK_PPC_DTPREL_HA:400case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:401case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:402case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:403case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:404case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:405case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:406case MCSymbolRefExpr::VK_PPC_GOT_TPREL:407case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:408case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:409case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:410case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL:411case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:412case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:413case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:414case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:415case MCSymbolRefExpr::VK_PPC_TLS:416case MCSymbolRefExpr::VK_PPC_TLS_PCREL:417case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:418case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:419case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:420case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:421case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL:422case MCSymbolRefExpr::VK_PPC_TLSGD:423case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:424case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:425case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:426case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:427case MCSymbolRefExpr::VK_PPC_TLSLD:428break;429}430getAssembler().registerSymbol(symRef.getSymbol());431cast<MCSymbolELF>(symRef.getSymbol()).setType(ELF::STT_TLS);432break;433}434435case MCExpr::Unary:436fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr());437break;438}439}440441void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,442uint64_t Offset) {443const MCSymbol *S = &SRE->getSymbol();444if (S->isTemporary()) {445if (!S->isInSection()) {446getContext().reportError(447SRE->getLoc(), Twine("Reference to undefined temporary symbol ") +448"`" + S->getName() + "`");449return;450}451S = S->getSection().getBeginSymbol();452S->setUsedInReloc();453SRE = MCSymbolRefExpr::create(S, MCSymbolRefExpr::VK_None, getContext(),454SRE->getLoc());455}456const MCConstantExpr *MCOffset = MCConstantExpr::create(Offset, getContext());457if (std::optional<std::pair<bool, std::string>> Err =458MCObjectStreamer::emitRelocDirective(459*MCOffset, "BFD_RELOC_NONE", SRE, SRE->getLoc(),460*getContext().getSubtargetInfo()))461report_fatal_error("Relocation for CG Profile could not be created: " +462Twine(Err->second));463}464465void MCELFStreamer::finalizeCGProfile() {466ELFObjectWriter &W = getWriter();467if (W.getCGProfile().empty())468return;469MCSection *CGProfile = getAssembler().getContext().getELFSection(470".llvm.call-graph-profile", ELF::SHT_LLVM_CALL_GRAPH_PROFILE,471ELF::SHF_EXCLUDE, /*sizeof(Elf_CGProfile_Impl<>)=*/8);472pushSection();473switchSection(CGProfile);474uint64_t Offset = 0;475for (auto &E : W.getCGProfile()) {476finalizeCGProfileEntry(E.From, Offset);477finalizeCGProfileEntry(E.To, Offset);478emitIntValue(E.Count, sizeof(uint64_t));479Offset += sizeof(uint64_t);480}481popSection();482}483484void MCELFStreamer::emitInstToFragment(const MCInst &Inst,485const MCSubtargetInfo &STI) {486this->MCObjectStreamer::emitInstToFragment(Inst, STI);487MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());488489for (auto &Fixup : F.getFixups())490fixSymbolsInTLSFixups(Fixup.getValue());491}492493// A fragment can only have one Subtarget, and when bundling is enabled we494// sometimes need to use the same fragment. We give an error if there495// are conflicting Subtargets.496static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI,497const MCSubtargetInfo *NewSTI) {498if (OldSTI && NewSTI && OldSTI != NewSTI)499report_fatal_error("A Bundle can only have one Subtarget.");500}501502void MCELFStreamer::emitInstToData(const MCInst &Inst,503const MCSubtargetInfo &STI) {504MCAssembler &Assembler = getAssembler();505506// There are several possibilities here:507//508// If bundling is disabled, append the encoded instruction to the current data509// fragment (or create a new such fragment if the current fragment is not a510// data fragment, or the Subtarget has changed).511//512// If bundling is enabled:513// - If we're not in a bundle-locked group, emit the instruction into a514// fragment of its own.515// - If we're in a bundle-locked group, append the instruction to the current516// data fragment because we want all the instructions in a group to get into517// the same fragment. Be careful not to do that for the first instruction in518// the group, though.519MCDataFragment *DF;520521if (Assembler.isBundlingEnabled()) {522MCSection &Sec = *getCurrentSectionOnly();523if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) {524// If we are bundle-locked, we re-use the current fragment.525// The bundle-locking directive ensures this is a new data fragment.526DF = cast<MCDataFragment>(getCurrentFragment());527CheckBundleSubtargets(DF->getSubtargetInfo(), &STI);528} else {529DF = getContext().allocFragment<MCDataFragment>();530insert(DF);531}532if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) {533// If this fragment is for a group marked "align_to_end", set a flag534// in the fragment. This can happen after the fragment has already been535// created if there are nested bundle_align groups and an inner one536// is the one marked align_to_end.537DF->setAlignToBundleEnd(true);538}539540// We're now emitting an instruction in a bundle group, so this flag has541// to be turned off.542Sec.setBundleGroupBeforeFirstInst(false);543} else {544DF = getOrCreateDataFragment(&STI);545}546547// Emit instruction directly into data fragment.548size_t FixupStartIndex = DF->getFixups().size();549size_t CodeOffset = DF->getContents().size();550Assembler.getEmitter().encodeInstruction(Inst, DF->getContents(),551DF->getFixups(), STI);552553auto Fixups = MutableArrayRef(DF->getFixups()).slice(FixupStartIndex);554for (auto &Fixup : Fixups) {555Fixup.setOffset(Fixup.getOffset() + CodeOffset);556fixSymbolsInTLSFixups(Fixup.getValue());557}558559DF->setHasInstructions(STI);560if (!Fixups.empty() && Fixups.back().getTargetKind() ==561getAssembler().getBackend().RelaxFixupKind)562DF->setLinkerRelaxable();563}564565void MCELFStreamer::emitBundleAlignMode(Align Alignment) {566assert(Log2(Alignment) <= 30 && "Invalid bundle alignment");567MCAssembler &Assembler = getAssembler();568if (Alignment > 1 && (Assembler.getBundleAlignSize() == 0 ||569Assembler.getBundleAlignSize() == Alignment.value()))570Assembler.setBundleAlignSize(Alignment.value());571else572report_fatal_error(".bundle_align_mode cannot be changed once set");573}574575void MCELFStreamer::emitBundleLock(bool AlignToEnd) {576MCSection &Sec = *getCurrentSectionOnly();577578if (!getAssembler().isBundlingEnabled())579report_fatal_error(".bundle_lock forbidden when bundling is disabled");580581if (!isBundleLocked())582Sec.setBundleGroupBeforeFirstInst(true);583584Sec.setBundleLockState(AlignToEnd ? MCSection::BundleLockedAlignToEnd585: MCSection::BundleLocked);586}587588void MCELFStreamer::emitBundleUnlock() {589MCSection &Sec = *getCurrentSectionOnly();590591if (!getAssembler().isBundlingEnabled())592report_fatal_error(".bundle_unlock forbidden when bundling is disabled");593else if (!isBundleLocked())594report_fatal_error(".bundle_unlock without matching lock");595else if (Sec.isBundleGroupBeforeFirstInst())596report_fatal_error("Empty bundle-locked group is forbidden");597598Sec.setBundleLockState(MCSection::NotBundleLocked);599}600601void MCELFStreamer::finishImpl() {602// Emit the .gnu attributes section if any attributes have been added.603if (!GNUAttributes.empty()) {604MCSection *DummyAttributeSection = nullptr;605createAttributesSection("gnu", ".gnu.attributes", ELF::SHT_GNU_ATTRIBUTES,606DummyAttributeSection, GNUAttributes);607}608609// Ensure the last section gets aligned if necessary.610if (MCFragment *F = getCurrentFragment())611setSectionAlignmentForBundling(getAssembler(), F->getParent());612613finalizeCGProfile();614emitFrames(nullptr);615616this->MCObjectStreamer::finishImpl();617}618619void MCELFStreamer::emitThumbFunc(MCSymbol *Func) {620llvm_unreachable("Generic ELF doesn't support this directive");621}622623void MCELFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {624llvm_unreachable("ELF doesn't support this directive");625}626627void MCELFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,628uint64_t Size, Align ByteAlignment,629SMLoc Loc) {630llvm_unreachable("ELF doesn't support this directive");631}632633void MCELFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,634uint64_t Size, Align ByteAlignment) {635llvm_unreachable("ELF doesn't support this directive");636}637638void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,639bool OverwriteExisting) {640// Look for existing attribute item641if (AttributeItem *Item = getAttributeItem(Attribute)) {642if (!OverwriteExisting)643return;644Item->Type = AttributeItem::NumericAttribute;645Item->IntValue = Value;646return;647}648649// Create new attribute item650AttributeItem Item = {AttributeItem::NumericAttribute, Attribute, Value,651std::string(StringRef(""))};652Contents.push_back(Item);653}654655void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,656bool OverwriteExisting) {657// Look for existing attribute item658if (AttributeItem *Item = getAttributeItem(Attribute)) {659if (!OverwriteExisting)660return;661Item->Type = AttributeItem::TextAttribute;662Item->StringValue = std::string(Value);663return;664}665666// Create new attribute item667AttributeItem Item = {AttributeItem::TextAttribute, Attribute, 0,668std::string(Value)};669Contents.push_back(Item);670}671672void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,673StringRef StringValue,674bool OverwriteExisting) {675// Look for existing attribute item676if (AttributeItem *Item = getAttributeItem(Attribute)) {677if (!OverwriteExisting)678return;679Item->Type = AttributeItem::NumericAndTextAttributes;680Item->IntValue = IntValue;681Item->StringValue = std::string(StringValue);682return;683}684685// Create new attribute item686AttributeItem Item = {AttributeItem::NumericAndTextAttributes, Attribute,687IntValue, std::string(StringValue)};688Contents.push_back(Item);689}690691MCELFStreamer::AttributeItem *692MCELFStreamer::getAttributeItem(unsigned Attribute) {693for (AttributeItem &Item : Contents)694if (Item.Tag == Attribute)695return &Item;696return nullptr;697}698699size_t700MCELFStreamer::calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) {701size_t Result = 0;702for (const AttributeItem &Item : AttrsVec) {703switch (Item.Type) {704case AttributeItem::HiddenAttribute:705break;706case AttributeItem::NumericAttribute:707Result += getULEB128Size(Item.Tag);708Result += getULEB128Size(Item.IntValue);709break;710case AttributeItem::TextAttribute:711Result += getULEB128Size(Item.Tag);712Result += Item.StringValue.size() + 1; // string + '\0'713break;714case AttributeItem::NumericAndTextAttributes:715Result += getULEB128Size(Item.Tag);716Result += getULEB128Size(Item.IntValue);717Result += Item.StringValue.size() + 1; // string + '\0';718break;719}720}721return Result;722}723724void MCELFStreamer::createAttributesSection(725StringRef Vendor, const Twine &Section, unsigned Type,726MCSection *&AttributeSection, SmallVector<AttributeItem, 64> &AttrsVec) {727// <format-version>728// [ <section-length> "vendor-name"729// [ <file-tag> <size> <attribute>*730// | <section-tag> <size> <section-number>* 0 <attribute>*731// | <symbol-tag> <size> <symbol-number>* 0 <attribute>*732// ]+733// ]*734735// Switch section to AttributeSection or get/create the section.736if (AttributeSection) {737switchSection(AttributeSection);738} else {739AttributeSection = getContext().getELFSection(Section, Type, 0);740switchSection(AttributeSection);741742// Format version743emitInt8(0x41);744}745746// Vendor size + Vendor name + '\0'747const size_t VendorHeaderSize = 4 + Vendor.size() + 1;748749// Tag + Tag Size750const size_t TagHeaderSize = 1 + 4;751752const size_t ContentsSize = calculateContentSize(AttrsVec);753754emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);755emitBytes(Vendor);756emitInt8(0); // '\0'757758emitInt8(ARMBuildAttrs::File);759emitInt32(TagHeaderSize + ContentsSize);760761// Size should have been accounted for already, now762// emit each field as its type (ULEB or String)763for (const AttributeItem &Item : AttrsVec) {764emitULEB128IntValue(Item.Tag);765switch (Item.Type) {766default:767llvm_unreachable("Invalid attribute type");768case AttributeItem::NumericAttribute:769emitULEB128IntValue(Item.IntValue);770break;771case AttributeItem::TextAttribute:772emitBytes(Item.StringValue);773emitInt8(0); // '\0'774break;775case AttributeItem::NumericAndTextAttributes:776emitULEB128IntValue(Item.IntValue);777emitBytes(Item.StringValue);778emitInt8(0); // '\0'779break;780}781}782783AttrsVec.clear();784}785786MCStreamer *llvm::createELFStreamer(MCContext &Context,787std::unique_ptr<MCAsmBackend> &&MAB,788std::unique_ptr<MCObjectWriter> &&OW,789std::unique_ptr<MCCodeEmitter> &&CE) {790MCELFStreamer *S =791new MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));792return S;793}794795796