xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file assembles .s files and emits ELF .o object files.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/MC/MCELFStreamer.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/MCELFObjectWriter.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCFixup.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 <cassert>
36 #include <cstdint>
37 
38 using namespace llvm;
39 
MCELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> TAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)40 MCELFStreamer::MCELFStreamer(MCContext &Context,
41                              std::unique_ptr<MCAsmBackend> TAB,
42                              std::unique_ptr<MCObjectWriter> OW,
43                              std::unique_ptr<MCCodeEmitter> Emitter)
44     : MCObjectStreamer(Context, std::move(TAB), std::move(OW),
45                        std::move(Emitter)) {}
46 
getWriter()47 ELFObjectWriter &MCELFStreamer::getWriter() {
48   return static_cast<ELFObjectWriter &>(getAssembler().getWriter());
49 }
50 
isBundleLocked() const51 bool MCELFStreamer::isBundleLocked() const {
52   return getCurrentSectionOnly()->isBundleLocked();
53 }
54 
initSections(bool NoExecStack,const MCSubtargetInfo & STI)55 void MCELFStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) {
56   MCContext &Ctx = getContext();
57   switchSection(Ctx.getObjectFileInfo()->getTextSection());
58   emitCodeAlignment(Align(Ctx.getObjectFileInfo()->getTextSectionAlignment()),
59                     &STI);
60 
61   if (NoExecStack)
62     switchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));
63 }
64 
emitLabel(MCSymbol * S,SMLoc Loc)65 void MCELFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
66   auto *Symbol = cast<MCSymbolELF>(S);
67   MCObjectStreamer::emitLabel(Symbol, Loc);
68 
69   const MCSectionELF &Section =
70       static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
71   if (Section.getFlags() & ELF::SHF_TLS)
72     Symbol->setType(ELF::STT_TLS);
73 }
74 
emitLabelAtPos(MCSymbol * S,SMLoc Loc,MCDataFragment & F,uint64_t Offset)75 void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F,
76                                    uint64_t Offset) {
77   auto *Symbol = cast<MCSymbolELF>(S);
78   MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset);
79 
80   const MCSectionELF &Section =
81       static_cast<const MCSectionELF &>(*getCurrentSectionOnly());
82   if (Section.getFlags() & ELF::SHF_TLS)
83     Symbol->setType(ELF::STT_TLS);
84 }
85 
86 // If bundle alignment is used and there are any instructions in the section, it
87 // needs to be aligned to at least the bundle size.
setSectionAlignmentForBundling(const MCAssembler & Assembler,MCSection * Section)88 static void setSectionAlignmentForBundling(const MCAssembler &Assembler,
89                                            MCSection *Section) {
90   if (Assembler.isBundlingEnabled() && Section->hasInstructions())
91     Section->ensureMinAlignment(Align(Assembler.getBundleAlignSize()));
92 }
93 
changeSection(MCSection * Section,uint32_t Subsection)94 void MCELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
95   MCAssembler &Asm = getAssembler();
96   if (auto *F = getCurrentFragment()) {
97     if (isBundleLocked())
98       report_fatal_error("Unterminated .bundle_lock when changing a section");
99 
100     // Ensure the previous section gets aligned if necessary.
101     setSectionAlignmentForBundling(Asm, F->getParent());
102   }
103   auto *SectionELF = static_cast<const MCSectionELF *>(Section);
104   const MCSymbol *Grp = SectionELF->getGroup();
105   if (Grp)
106     Asm.registerSymbol(*Grp);
107   if (SectionELF->getFlags() & ELF::SHF_GNU_RETAIN)
108     getWriter().markGnuAbi();
109 
110   changeSectionImpl(Section, Subsection);
111   Asm.registerSymbol(*Section->getBeginSymbol());
112 }
113 
emitWeakReference(MCSymbol * Alias,const MCSymbol * Target)114 void MCELFStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) {
115   auto *A = cast<MCSymbolELF>(Alias);
116   if (A->isDefined()) {
117     getContext().reportError(getStartTokLoc(), "symbol '" + A->getName() +
118                                                    "' is already defined");
119     return;
120   }
121   A->setVariableValue(MCSymbolRefExpr::create(Target, getContext()));
122   A->setIsWeakref();
123   getWriter().Weakrefs.push_back(A);
124 }
125 
126 // When GNU as encounters more than one .type declaration for an object it seems
127 // to use a mechanism similar to the one below to decide which type is actually
128 // used in the object file.  The greater of T1 and T2 is selected based on the
129 // following ordering:
130 //  STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else
131 // If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user
132 // provided type).
CombineSymbolTypes(unsigned T1,unsigned T2)133 static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) {
134   for (unsigned Type : {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC,
135                         ELF::STT_GNU_IFUNC, ELF::STT_TLS}) {
136     if (T1 == Type)
137       return T2;
138     if (T2 == Type)
139       return T1;
140   }
141 
142   return T2;
143 }
144 
emitSymbolAttribute(MCSymbol * S,MCSymbolAttr Attribute)145 bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
146   auto *Symbol = cast<MCSymbolELF>(S);
147 
148   // Adding a symbol attribute always introduces the symbol, note that an
149   // important side effect of calling registerSymbol here is to register
150   // the symbol with the assembler.
151   getAssembler().registerSymbol(*Symbol);
152 
153   // The implementation of symbol attributes is designed to match 'as', but it
154   // leaves much to desired. It doesn't really make sense to arbitrarily add and
155   // remove flags, but 'as' allows this (in particular, see .desc).
156   //
157   // In the future it might be worth trying to make these operations more well
158   // defined.
159   switch (Attribute) {
160   case MCSA_Cold:
161   case MCSA_Extern:
162   case MCSA_LazyReference:
163   case MCSA_Reference:
164   case MCSA_SymbolResolver:
165   case MCSA_PrivateExtern:
166   case MCSA_WeakDefinition:
167   case MCSA_WeakDefAutoPrivate:
168   case MCSA_Invalid:
169   case MCSA_IndirectSymbol:
170   case MCSA_Exported:
171   case MCSA_WeakAntiDep:
172     return false;
173 
174   case MCSA_NoDeadStrip:
175     // Ignore for now.
176     break;
177 
178   case MCSA_ELF_TypeGnuUniqueObject:
179     Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));
180     Symbol->setBinding(ELF::STB_GNU_UNIQUE);
181     getWriter().markGnuAbi();
182     break;
183 
184   case MCSA_Global:
185     // For `.weak x; .global x`, GNU as sets the binding to STB_WEAK while we
186     // traditionally set the binding to STB_GLOBAL. This is error-prone, so we
187     // error on such cases. Note, we also disallow changed binding from .local.
188     if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_GLOBAL)
189       getContext().reportError(getStartTokLoc(),
190                                Symbol->getName() +
191                                    " changed binding to STB_GLOBAL");
192     Symbol->setBinding(ELF::STB_GLOBAL);
193     break;
194 
195   case MCSA_WeakReference:
196   case MCSA_Weak:
197     // For `.global x; .weak x`, both MC and GNU as set the binding to STB_WEAK.
198     // We emit a warning for now but may switch to an error in the future.
199     if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_WEAK)
200       getContext().reportWarning(
201           getStartTokLoc(), Symbol->getName() + " changed binding to STB_WEAK");
202     Symbol->setBinding(ELF::STB_WEAK);
203     break;
204 
205   case MCSA_Local:
206     if (Symbol->isBindingSet() && Symbol->getBinding() != ELF::STB_LOCAL)
207       getContext().reportError(getStartTokLoc(),
208                                Symbol->getName() +
209                                    " changed binding to STB_LOCAL");
210     Symbol->setBinding(ELF::STB_LOCAL);
211     break;
212 
213   case MCSA_ELF_TypeFunction:
214     Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_FUNC));
215     break;
216 
217   case MCSA_ELF_TypeIndFunction:
218     Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_GNU_IFUNC));
219     getWriter().markGnuAbi();
220     break;
221 
222   case MCSA_ELF_TypeObject:
223     Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));
224     break;
225 
226   case MCSA_ELF_TypeTLS:
227     Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_TLS));
228     break;
229 
230   case MCSA_ELF_TypeCommon:
231     // TODO: Emit these as a common symbol.
232     Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));
233     break;
234 
235   case MCSA_ELF_TypeNoType:
236     Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_NOTYPE));
237     break;
238 
239   case MCSA_Protected:
240     Symbol->setVisibility(ELF::STV_PROTECTED);
241     break;
242 
243   case MCSA_Memtag:
244     Symbol->setMemtag(true);
245     break;
246 
247   case MCSA_Hidden:
248     Symbol->setVisibility(ELF::STV_HIDDEN);
249     break;
250 
251   case MCSA_Internal:
252     Symbol->setVisibility(ELF::STV_INTERNAL);
253     break;
254 
255   case MCSA_AltEntry:
256     llvm_unreachable("ELF doesn't support the .alt_entry attribute");
257 
258   case MCSA_LGlobal:
259     llvm_unreachable("ELF doesn't support the .lglobl attribute");
260   }
261 
262   return true;
263 }
264 
emitCommonSymbol(MCSymbol * S,uint64_t Size,Align ByteAlignment)265 void MCELFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
266                                      Align ByteAlignment) {
267   auto *Symbol = cast<MCSymbolELF>(S);
268   getAssembler().registerSymbol(*Symbol);
269 
270   if (!Symbol->isBindingSet())
271     Symbol->setBinding(ELF::STB_GLOBAL);
272 
273   Symbol->setType(ELF::STT_OBJECT);
274 
275   if (Symbol->getBinding() == ELF::STB_LOCAL) {
276     MCSection &Section = *getAssembler().getContext().getELFSection(
277         ".bss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
278     MCSectionSubPair P = getCurrentSection();
279     switchSection(&Section);
280 
281     emitValueToAlignment(ByteAlignment, 0, 1, 0);
282     emitLabel(Symbol);
283     emitZeros(Size);
284 
285     switchSection(P.first, P.second);
286   } else {
287     if (Symbol->declareCommon(Size, ByteAlignment))
288       report_fatal_error(Twine("Symbol: ") + Symbol->getName() +
289                          " redeclared as different type");
290   }
291 
292   cast<MCSymbolELF>(Symbol)
293       ->setSize(MCConstantExpr::create(Size, getContext()));
294 }
295 
emitELFSize(MCSymbol * Symbol,const MCExpr * Value)296 void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
297   cast<MCSymbolELF>(Symbol)->setSize(Value);
298 }
299 
emitELFSymverDirective(const MCSymbol * OriginalSym,StringRef Name,bool KeepOriginalSym)300 void MCELFStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
301                                            StringRef Name,
302                                            bool KeepOriginalSym) {
303   getWriter().Symvers.push_back(ELFObjectWriter::Symver{
304       getStartTokLoc(), OriginalSym, Name, KeepOriginalSym});
305 }
306 
emitLocalCommonSymbol(MCSymbol * S,uint64_t Size,Align ByteAlignment)307 void MCELFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
308                                           Align ByteAlignment) {
309   auto *Symbol = cast<MCSymbolELF>(S);
310   // FIXME: Should this be caught and done earlier?
311   getAssembler().registerSymbol(*Symbol);
312   Symbol->setBinding(ELF::STB_LOCAL);
313   emitCommonSymbol(Symbol, Size, ByteAlignment);
314 }
315 
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)316 void MCELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
317                                   SMLoc Loc) {
318   if (isBundleLocked())
319     report_fatal_error("Emitting values inside a locked bundle is forbidden");
320   MCObjectStreamer::emitValueImpl(Value, Size, Loc);
321 }
322 
emitValueToAlignment(Align Alignment,int64_t Value,uint8_t ValueSize,unsigned MaxBytesToEmit)323 void MCELFStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
324                                          uint8_t ValueSize,
325                                          unsigned MaxBytesToEmit) {
326   if (isBundleLocked())
327     report_fatal_error("Emitting values inside a locked bundle is forbidden");
328   MCObjectStreamer::emitValueToAlignment(Alignment, Value, ValueSize,
329                                          MaxBytesToEmit);
330 }
331 
emitCGProfileEntry(const MCSymbolRefExpr * From,const MCSymbolRefExpr * To,uint64_t Count)332 void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
333                                        const MCSymbolRefExpr *To,
334                                        uint64_t Count) {
335   getWriter().getCGProfile().push_back({From, To, Count});
336 }
337 
emitIdent(StringRef IdentString)338 void MCELFStreamer::emitIdent(StringRef IdentString) {
339   MCSection *Comment = getAssembler().getContext().getELFSection(
340       ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1);
341   pushSection();
342   switchSection(Comment);
343   if (!SeenIdent) {
344     emitInt8(0);
345     SeenIdent = true;
346   }
347   emitBytes(IdentString);
348   emitInt8(0);
349   popSection();
350 }
351 
finalizeCGProfileEntry(const MCSymbolRefExpr * & SRE,uint64_t Offset)352 void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
353                                            uint64_t Offset) {
354   const MCSymbol *S = &SRE->getSymbol();
355   if (S->isTemporary()) {
356     if (!S->isInSection()) {
357       getContext().reportError(
358           SRE->getLoc(), Twine("Reference to undefined temporary symbol ") +
359                              "`" + S->getName() + "`");
360       return;
361     }
362     S = S->getSection().getBeginSymbol();
363     S->setUsedInReloc();
364     SRE = MCSymbolRefExpr::create(S, getContext(), SRE->getLoc());
365   }
366   const MCConstantExpr *MCOffset = MCConstantExpr::create(Offset, getContext());
367   if (std::optional<std::pair<bool, std::string>> Err =
368           MCObjectStreamer::emitRelocDirective(
369               *MCOffset, "BFD_RELOC_NONE", SRE, SRE->getLoc(),
370               *getContext().getSubtargetInfo()))
371     report_fatal_error("Relocation for CG Profile could not be created: " +
372                        Twine(Err->second));
373 }
374 
finalizeCGProfile()375 void MCELFStreamer::finalizeCGProfile() {
376   ELFObjectWriter &W = getWriter();
377   if (W.getCGProfile().empty())
378     return;
379   MCSection *CGProfile = getAssembler().getContext().getELFSection(
380       ".llvm.call-graph-profile", ELF::SHT_LLVM_CALL_GRAPH_PROFILE,
381       ELF::SHF_EXCLUDE, /*sizeof(Elf_CGProfile_Impl<>)=*/8);
382   pushSection();
383   switchSection(CGProfile);
384   uint64_t Offset = 0;
385   for (auto &E : W.getCGProfile()) {
386     finalizeCGProfileEntry(E.From, Offset);
387     finalizeCGProfileEntry(E.To, Offset);
388     emitIntValue(E.Count, sizeof(uint64_t));
389     Offset += sizeof(uint64_t);
390   }
391   popSection();
392 }
393 
394 // A fragment can only have one Subtarget, and when bundling is enabled we
395 // sometimes need to use the same fragment. We give an error if there
396 // are conflicting Subtargets.
CheckBundleSubtargets(const MCSubtargetInfo * OldSTI,const MCSubtargetInfo * NewSTI)397 static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI,
398                                   const MCSubtargetInfo *NewSTI) {
399   if (OldSTI && NewSTI && OldSTI != NewSTI)
400     report_fatal_error("A Bundle can only have one Subtarget.");
401 }
402 
emitInstToData(const MCInst & Inst,const MCSubtargetInfo & STI)403 void MCELFStreamer::emitInstToData(const MCInst &Inst,
404                                    const MCSubtargetInfo &STI) {
405   MCAssembler &Assembler = getAssembler();
406 
407   // There are several possibilities here:
408   //
409   // If bundling is disabled, append the encoded instruction to the current data
410   // fragment (or create a new such fragment if the current fragment is not a
411   // data fragment, or the Subtarget has changed).
412   //
413   // If bundling is enabled:
414   // - If we're not in a bundle-locked group, emit the instruction into a
415   //   fragment of its own.
416   // - If we're in a bundle-locked group, append the instruction to the current
417   //   data fragment because we want all the instructions in a group to get into
418   //   the same fragment. Be careful not to do that for the first instruction in
419   //   the group, though.
420   MCDataFragment *DF;
421 
422   if (Assembler.isBundlingEnabled()) {
423     MCSection &Sec = *getCurrentSectionOnly();
424     if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) {
425       // If we are bundle-locked, we re-use the current fragment.
426       // The bundle-locking directive ensures this is a new data fragment.
427       DF = cast<MCDataFragment>(getCurrentFragment());
428       CheckBundleSubtargets(DF->getSubtargetInfo(), &STI);
429     } else {
430       DF = getContext().allocFragment<MCDataFragment>();
431       insert(DF);
432     }
433     if (Sec.getBundleLockState() == MCSection::BundleLockedAlignToEnd) {
434       // If this fragment is for a group marked "align_to_end", set a flag
435       // in the fragment. This can happen after the fragment has already been
436       // created if there are nested bundle_align groups and an inner one
437       // is the one marked align_to_end.
438       DF->setAlignToBundleEnd(true);
439     }
440 
441     // We're now emitting an instruction in a bundle group, so this flag has
442     // to be turned off.
443     Sec.setBundleGroupBeforeFirstInst(false);
444   } else {
445     DF = getOrCreateDataFragment(&STI);
446   }
447 
448   // Emit instruction directly into data fragment.
449   size_t FixupStartIndex = DF->getFixups().size();
450   size_t CodeOffset = DF->getContents().size();
451   SmallVector<MCFixup, 1> Fixups;
452   Assembler.getEmitter().encodeInstruction(Inst, DF->getContentsForAppending(),
453                                            Fixups, STI);
454   DF->doneAppending();
455   if (!Fixups.empty())
456     DF->appendFixups(Fixups);
457 
458   for (auto &Fixup : MutableArrayRef(DF->getFixups()).slice(FixupStartIndex)) {
459     Fixup.setOffset(Fixup.getOffset() + CodeOffset);
460     if (Fixup.isLinkerRelaxable()) {
461       DF->setLinkerRelaxable();
462       getCurrentSectionOnly()->setLinkerRelaxable();
463     }
464   }
465 
466   DF->setHasInstructions(STI);
467 }
468 
emitBundleAlignMode(Align Alignment)469 void MCELFStreamer::emitBundleAlignMode(Align Alignment) {
470   assert(Log2(Alignment) <= 30 && "Invalid bundle alignment");
471   MCAssembler &Assembler = getAssembler();
472   if (Alignment > 1 && (Assembler.getBundleAlignSize() == 0 ||
473                         Assembler.getBundleAlignSize() == Alignment.value()))
474     Assembler.setBundleAlignSize(Alignment.value());
475   else
476     report_fatal_error(".bundle_align_mode cannot be changed once set");
477 }
478 
emitBundleLock(bool AlignToEnd)479 void MCELFStreamer::emitBundleLock(bool AlignToEnd) {
480   MCSection &Sec = *getCurrentSectionOnly();
481 
482   if (!getAssembler().isBundlingEnabled())
483     report_fatal_error(".bundle_lock forbidden when bundling is disabled");
484 
485   if (!isBundleLocked())
486     Sec.setBundleGroupBeforeFirstInst(true);
487 
488   Sec.setBundleLockState(AlignToEnd ? MCSection::BundleLockedAlignToEnd
489                                     : MCSection::BundleLocked);
490 }
491 
emitBundleUnlock()492 void MCELFStreamer::emitBundleUnlock() {
493   MCSection &Sec = *getCurrentSectionOnly();
494 
495   if (!getAssembler().isBundlingEnabled())
496     report_fatal_error(".bundle_unlock forbidden when bundling is disabled");
497   else if (!isBundleLocked())
498     report_fatal_error(".bundle_unlock without matching lock");
499   else if (Sec.isBundleGroupBeforeFirstInst())
500     report_fatal_error("Empty bundle-locked group is forbidden");
501 
502   Sec.setBundleLockState(MCSection::NotBundleLocked);
503 }
504 
finishImpl()505 void MCELFStreamer::finishImpl() {
506   // Emit the .gnu attributes section if any attributes have been added.
507   if (!GNUAttributes.empty()) {
508     MCSection *DummyAttributeSection = nullptr;
509     createAttributesSection("gnu", ".gnu.attributes", ELF::SHT_GNU_ATTRIBUTES,
510                             DummyAttributeSection, GNUAttributes);
511   }
512 
513   // Ensure the last section gets aligned if necessary.
514   if (MCFragment *F = getCurrentFragment())
515     setSectionAlignmentForBundling(getAssembler(), F->getParent());
516 
517   finalizeCGProfile();
518   emitFrames(nullptr);
519 
520   this->MCObjectStreamer::finishImpl();
521 }
522 
setAttributeItem(unsigned Attribute,unsigned Value,bool OverwriteExisting)523 void MCELFStreamer::setAttributeItem(unsigned Attribute, unsigned Value,
524                                      bool OverwriteExisting) {
525   // Look for existing attribute item
526   if (AttributeItem *Item = getAttributeItem(Attribute)) {
527     if (!OverwriteExisting)
528       return;
529     Item->Type = AttributeItem::NumericAttribute;
530     Item->IntValue = Value;
531     return;
532   }
533 
534   // Create new attribute item
535   AttributeItem Item = {AttributeItem::NumericAttribute, Attribute, Value,
536                         std::string(StringRef(""))};
537   Contents.push_back(Item);
538 }
539 
setAttributeItem(unsigned Attribute,StringRef Value,bool OverwriteExisting)540 void MCELFStreamer::setAttributeItem(unsigned Attribute, StringRef Value,
541                                      bool OverwriteExisting) {
542   // Look for existing attribute item
543   if (AttributeItem *Item = getAttributeItem(Attribute)) {
544     if (!OverwriteExisting)
545       return;
546     Item->Type = AttributeItem::TextAttribute;
547     Item->StringValue = std::string(Value);
548     return;
549   }
550 
551   // Create new attribute item
552   AttributeItem Item = {AttributeItem::TextAttribute, Attribute, 0,
553                         std::string(Value)};
554   Contents.push_back(Item);
555 }
556 
setAttributeItems(unsigned Attribute,unsigned IntValue,StringRef StringValue,bool OverwriteExisting)557 void MCELFStreamer::setAttributeItems(unsigned Attribute, unsigned IntValue,
558                                       StringRef StringValue,
559                                       bool OverwriteExisting) {
560   // Look for existing attribute item
561   if (AttributeItem *Item = getAttributeItem(Attribute)) {
562     if (!OverwriteExisting)
563       return;
564     Item->Type = AttributeItem::NumericAndTextAttributes;
565     Item->IntValue = IntValue;
566     Item->StringValue = std::string(StringValue);
567     return;
568   }
569 
570   // Create new attribute item
571   AttributeItem Item = {AttributeItem::NumericAndTextAttributes, Attribute,
572                         IntValue, std::string(StringValue)};
573   Contents.push_back(Item);
574 }
575 
576 MCELFStreamer::AttributeItem *
getAttributeItem(unsigned Attribute)577 MCELFStreamer::getAttributeItem(unsigned Attribute) {
578   for (AttributeItem &Item : Contents)
579     if (Item.Tag == Attribute)
580       return &Item;
581   return nullptr;
582 }
583 
calculateContentSize(SmallVector<AttributeItem,64> & AttrsVec) const584 size_t MCELFStreamer::calculateContentSize(
585     SmallVector<AttributeItem, 64> &AttrsVec) const {
586   size_t Result = 0;
587   for (const AttributeItem &Item : AttrsVec) {
588     switch (Item.Type) {
589     case AttributeItem::HiddenAttribute:
590       break;
591     case AttributeItem::NumericAttribute:
592       Result += getULEB128Size(Item.Tag);
593       Result += getULEB128Size(Item.IntValue);
594       break;
595     case AttributeItem::TextAttribute:
596       Result += getULEB128Size(Item.Tag);
597       Result += Item.StringValue.size() + 1; // string + '\0'
598       break;
599     case AttributeItem::NumericAndTextAttributes:
600       Result += getULEB128Size(Item.Tag);
601       Result += getULEB128Size(Item.IntValue);
602       Result += Item.StringValue.size() + 1; // string + '\0';
603       break;
604     }
605   }
606   return Result;
607 }
608 
createAttributesSection(StringRef Vendor,const Twine & Section,unsigned Type,MCSection * & AttributeSection,SmallVector<AttributeItem,64> & AttrsVec)609 void MCELFStreamer::createAttributesSection(
610     StringRef Vendor, const Twine &Section, unsigned Type,
611     MCSection *&AttributeSection, SmallVector<AttributeItem, 64> &AttrsVec) {
612   // <format-version>
613   // [ <section-length> "vendor-name"
614   // [ <file-tag> <size> <attribute>*
615   //   | <section-tag> <size> <section-number>* 0 <attribute>*
616   //   | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
617   //   ]+
618   // ]*
619 
620   // Switch section to AttributeSection or get/create the section.
621   if (AttributeSection) {
622     switchSection(AttributeSection);
623   } else {
624     AttributeSection = getContext().getELFSection(Section, Type, 0);
625     switchSection(AttributeSection);
626 
627     // Format version
628     emitInt8(0x41);
629   }
630 
631   // Vendor size + Vendor name + '\0'
632   const size_t VendorHeaderSize = 4 + Vendor.size() + 1;
633 
634   // Tag + Tag Size
635   const size_t TagHeaderSize = 1 + 4;
636 
637   const size_t ContentsSize = calculateContentSize(AttrsVec);
638 
639   emitInt32(VendorHeaderSize + TagHeaderSize + ContentsSize);
640   emitBytes(Vendor);
641   emitInt8(0); // '\0'
642 
643   emitInt8(ARMBuildAttrs::File);
644   emitInt32(TagHeaderSize + ContentsSize);
645 
646   // Size should have been accounted for already, now
647   // emit each field as its type (ULEB or String)
648   for (const AttributeItem &Item : AttrsVec) {
649     emitULEB128IntValue(Item.Tag);
650     switch (Item.Type) {
651     default:
652       llvm_unreachable("Invalid attribute type");
653     case AttributeItem::NumericAttribute:
654       emitULEB128IntValue(Item.IntValue);
655       break;
656     case AttributeItem::TextAttribute:
657       emitBytes(Item.StringValue);
658       emitInt8(0); // '\0'
659       break;
660     case AttributeItem::NumericAndTextAttributes:
661       emitULEB128IntValue(Item.IntValue);
662       emitBytes(Item.StringValue);
663       emitInt8(0); // '\0'
664       break;
665     }
666   }
667 
668   AttrsVec.clear();
669 }
670 
createAttributesWithSubsection(MCSection * & AttributeSection,const Twine & Section,unsigned Type,SmallVector<AttributeSubSection,64> & SubSectionVec)671 void MCELFStreamer::createAttributesWithSubsection(
672     MCSection *&AttributeSection, const Twine &Section, unsigned Type,
673     SmallVector<AttributeSubSection, 64> &SubSectionVec) {
674   // <format-version: 'A'>
675   // [ <uint32: subsection-length> NTBS: vendor-name
676   //   <bytes: vendor-data>
677   // ]*
678   // vendor-data expends to:
679   // <uint8: optional> <uint8: parameter type> <attribute>*
680   if (0 == SubSectionVec.size()) {
681     return;
682   }
683 
684   // Switch section to AttributeSection or get/create the section.
685   if (AttributeSection) {
686     switchSection(AttributeSection);
687   } else {
688     AttributeSection = getContext().getELFSection(Section, Type, 0);
689     switchSection(AttributeSection);
690 
691     // Format version
692     emitInt8(0x41);
693   }
694 
695   for (AttributeSubSection &SubSection : SubSectionVec) {
696     // subsection-length + vendor-name + '\0'
697     const size_t VendorHeaderSize = 4 + SubSection.VendorName.size() + 1;
698     // optional + parameter-type
699     const size_t VendorParameters = 1 + 1;
700     const size_t ContentsSize = calculateContentSize(SubSection.Content);
701 
702     emitInt32(VendorHeaderSize + VendorParameters + ContentsSize);
703     emitBytes(SubSection.VendorName);
704     emitInt8(0); // '\0'
705     emitInt8(SubSection.IsOptional);
706     emitInt8(SubSection.ParameterType);
707 
708     for (AttributeItem &Item : SubSection.Content) {
709       emitULEB128IntValue(Item.Tag);
710       switch (Item.Type) {
711       default:
712         assert(0 && "Invalid attribute type");
713         break;
714       case AttributeItem::NumericAttribute:
715         emitULEB128IntValue(Item.IntValue);
716         break;
717       case AttributeItem::TextAttribute:
718         emitBytes(Item.StringValue);
719         emitInt8(0); // '\0'
720         break;
721       case AttributeItem::NumericAndTextAttributes:
722         emitULEB128IntValue(Item.IntValue);
723         emitBytes(Item.StringValue);
724         emitInt8(0); // '\0'
725         break;
726       }
727     }
728   }
729   SubSectionVec.clear();
730 }
731 
createELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> && MAB,std::unique_ptr<MCObjectWriter> && OW,std::unique_ptr<MCCodeEmitter> && CE)732 MCStreamer *llvm::createELFStreamer(MCContext &Context,
733                                     std::unique_ptr<MCAsmBackend> &&MAB,
734                                     std::unique_ptr<MCObjectWriter> &&OW,
735                                     std::unique_ptr<MCCodeEmitter> &&CE) {
736   MCELFStreamer *S =
737       new MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
738   return S;
739 }
740