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
38using namespace llvm;
39
40MCELFStreamer::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
47ELFObjectWriter &MCELFStreamer::getWriter() {
48 return static_cast<ELFObjectWriter &>(getAssembler().getWriter());
49}
50
51bool MCELFStreamer::isBundleLocked() const {
52 return getCurrentSectionOnly()->isBundleLocked();
53}
54
55void MCELFStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) {
56 MCContext &Ctx = getContext();
57 switchSection(Section: Ctx.getObjectFileInfo()->getTextSection());
58 emitCodeAlignment(ByteAlignment: Align(Ctx.getObjectFileInfo()->getTextSectionAlignment()),
59 STI: &STI);
60
61 if (NoExecStack)
62 switchSection(Section: Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));
63}
64
65void MCELFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
66 auto *Symbol = cast<MCSymbolELF>(Val: 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
75void MCELFStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F,
76 uint64_t Offset) {
77 auto *Symbol = cast<MCSymbolELF>(Val: 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.
88static void setSectionAlignmentForBundling(const MCAssembler &Assembler,
89 MCSection *Section) {
90 if (Assembler.isBundlingEnabled() && Section->hasInstructions())
91 Section->ensureMinAlignment(MinAlignment: Align(Assembler.getBundleAlignSize()));
92}
93
94void MCELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
95 MCAssembler &Asm = getAssembler();
96 if (auto *F = getCurrentFragment()) {
97 if (isBundleLocked())
98 report_fatal_error(reason: "Unterminated .bundle_lock when changing a section");
99
100 // Ensure the previous section gets aligned if necessary.
101 setSectionAlignmentForBundling(Assembler: Asm, Section: F->getParent());
102 }
103 auto *SectionELF = static_cast<const MCSectionELF *>(Section);
104 const MCSymbol *Grp = SectionELF->getGroup();
105 if (Grp)
106 Asm.registerSymbol(Symbol: *Grp);
107 if (SectionELF->getFlags() & ELF::SHF_GNU_RETAIN)
108 getWriter().markGnuAbi();
109
110 changeSectionImpl(Section, Subsection);
111 Asm.registerSymbol(Symbol: *Section->getBeginSymbol());
112}
113
114void MCELFStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) {
115 auto *A = cast<MCSymbolELF>(Val: Alias);
116 if (A->isDefined()) {
117 getContext().reportError(L: getStartTokLoc(), Msg: "symbol '" + A->getName() +
118 "' is already defined");
119 return;
120 }
121 A->setVariableValue(MCSymbolRefExpr::create(Symbol: Target, Ctx&: getContext()));
122 A->setIsWeakref();
123 getWriter().Weakrefs.push_back(Elt: 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).
133static 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
145bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
146 auto *Symbol = cast<MCSymbolELF>(Val: 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: *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(T1: Symbol->getType(), T2: 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(L: getStartTokLoc(),
190 Msg: 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 L: getStartTokLoc(), Msg: 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(L: getStartTokLoc(),
208 Msg: 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(T1: Symbol->getType(), T2: ELF::STT_FUNC));
215 break;
216
217 case MCSA_ELF_TypeIndFunction:
218 Symbol->setType(CombineSymbolTypes(T1: Symbol->getType(), T2: ELF::STT_GNU_IFUNC));
219 getWriter().markGnuAbi();
220 break;
221
222 case MCSA_ELF_TypeObject:
223 Symbol->setType(CombineSymbolTypes(T1: Symbol->getType(), T2: ELF::STT_OBJECT));
224 break;
225
226 case MCSA_ELF_TypeTLS:
227 Symbol->setType(CombineSymbolTypes(T1: Symbol->getType(), T2: ELF::STT_TLS));
228 break;
229
230 case MCSA_ELF_TypeCommon:
231 // TODO: Emit these as a common symbol.
232 Symbol->setType(CombineSymbolTypes(T1: Symbol->getType(), T2: ELF::STT_OBJECT));
233 break;
234
235 case MCSA_ELF_TypeNoType:
236 Symbol->setType(CombineSymbolTypes(T1: Symbol->getType(), T2: 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
265void MCELFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
266 Align ByteAlignment) {
267 auto *Symbol = cast<MCSymbolELF>(Val: S);
268 getAssembler().registerSymbol(Symbol: *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 Section: ".bss", Type: ELF::SHT_NOBITS, Flags: ELF::SHF_WRITE | ELF::SHF_ALLOC);
278 MCSectionSubPair P = getCurrentSection();
279 switchSection(Section: &Section);
280
281 emitValueToAlignment(ByteAlignment, 0, 1, 0);
282 emitLabel(S: Symbol);
283 emitZeros(NumBytes: Size);
284
285 switchSection(Section: P.first, Subsec: P.second);
286 } else {
287 if (Symbol->declareCommon(Size, Alignment: ByteAlignment))
288 report_fatal_error(reason: Twine("Symbol: ") + Symbol->getName() +
289 " redeclared as different type");
290 }
291
292 cast<MCSymbolELF>(Val: Symbol)
293 ->setSize(MCConstantExpr::create(Value: Size, Ctx&: getContext()));
294}
295
296void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
297 cast<MCSymbolELF>(Val: Symbol)->setSize(Value);
298}
299
300void MCELFStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
301 StringRef Name,
302 bool KeepOriginalSym) {
303 getWriter().Symvers.push_back(Elt: ELFObjectWriter::Symver{
304 .Loc: getStartTokLoc(), .Sym: OriginalSym, .Name: Name, .KeepOriginalSym: KeepOriginalSym});
305}
306
307void MCELFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
308 Align ByteAlignment) {
309 auto *Symbol = cast<MCSymbolELF>(Val: S);
310 // FIXME: Should this be caught and done earlier?
311 getAssembler().registerSymbol(Symbol: *Symbol);
312 Symbol->setBinding(ELF::STB_LOCAL);
313 emitCommonSymbol(S: Symbol, Size, ByteAlignment);
314}
315
316void MCELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
317 SMLoc Loc) {
318 if (isBundleLocked())
319 report_fatal_error(reason: "Emitting values inside a locked bundle is forbidden");
320 MCObjectStreamer::emitValueImpl(Value, Size, Loc);
321}
322
323void MCELFStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
324 unsigned ValueSize,
325 unsigned MaxBytesToEmit) {
326 if (isBundleLocked())
327 report_fatal_error(reason: "Emitting values inside a locked bundle is forbidden");
328 MCObjectStreamer::emitValueToAlignment(Alignment, Value, ValueSize,
329 MaxBytesToEmit);
330}
331
332void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
333 const MCSymbolRefExpr *To,
334 uint64_t Count) {
335 getWriter().getCGProfile().push_back(Elt: {.From: From, .To: To, .Count: Count});
336}
337
338void MCELFStreamer::emitIdent(StringRef IdentString) {
339 MCSection *Comment = getAssembler().getContext().getELFSection(
340 Section: ".comment", Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_MERGE | ELF::SHF_STRINGS, EntrySize: 1);
341 pushSection();
342 switchSection(Section: Comment);
343 if (!SeenIdent) {
344 emitInt8(Value: 0);
345 SeenIdent = true;
346 }
347 emitBytes(Data: IdentString);
348 emitInt8(Value: 0);
349 popSection();
350}
351
352void 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 L: SRE->getLoc(), Msg: Twine("Reference to undefined temporary symbol ") +
359 "`" + S->getName() + "`");
360 return;
361 }
362 S = S->getSection().getBeginSymbol();
363 S->setUsedInReloc();
364 SRE = MCSymbolRefExpr::create(Symbol: S, Ctx&: getContext(), Loc: SRE->getLoc());
365 }
366 const MCConstantExpr *MCOffset = MCConstantExpr::create(Value: Offset, Ctx&: getContext());
367 if (std::optional<std::pair<bool, std::string>> Err =
368 MCObjectStreamer::emitRelocDirective(
369 Offset: *MCOffset, Name: "BFD_RELOC_NONE", Expr: SRE, Loc: SRE->getLoc(),
370 STI: *getContext().getSubtargetInfo()))
371 report_fatal_error(reason: "Relocation for CG Profile could not be created: " +
372 Twine(Err->second));
373}
374
375void MCELFStreamer::finalizeCGProfile() {
376 ELFObjectWriter &W = getWriter();
377 if (W.getCGProfile().empty())
378 return;
379 MCSection *CGProfile = getAssembler().getContext().getELFSection(
380 Section: ".llvm.call-graph-profile", Type: ELF::SHT_LLVM_CALL_GRAPH_PROFILE,
381 Flags: ELF::SHF_EXCLUDE, /*sizeof(Elf_CGProfile_Impl<>)=*/EntrySize: 8);
382 pushSection();
383 switchSection(Section: CGProfile);
384 uint64_t Offset = 0;
385 for (auto &E : W.getCGProfile()) {
386 finalizeCGProfileEntry(SRE&: E.From, Offset);
387 finalizeCGProfileEntry(SRE&: E.To, Offset);
388 emitIntValue(Value: E.Count, Size: 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.
397static void CheckBundleSubtargets(const MCSubtargetInfo *OldSTI,
398 const MCSubtargetInfo *NewSTI) {
399 if (OldSTI && NewSTI && OldSTI != NewSTI)
400 report_fatal_error(reason: "A Bundle can only have one Subtarget.");
401}
402
403void 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>(Val: getCurrentFragment());
428 CheckBundleSubtargets(OldSTI: DF->getSubtargetInfo(), NewSTI: &STI);
429 } else {
430 DF = getContext().allocFragment<MCDataFragment>();
431 insert(F: 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: &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, CB&: 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(N: 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
469void 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(reason: ".bundle_align_mode cannot be changed once set");
477}
478
479void MCELFStreamer::emitBundleLock(bool AlignToEnd) {
480 MCSection &Sec = *getCurrentSectionOnly();
481
482 if (!getAssembler().isBundlingEnabled())
483 report_fatal_error(reason: ".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
492void MCELFStreamer::emitBundleUnlock() {
493 MCSection &Sec = *getCurrentSectionOnly();
494
495 if (!getAssembler().isBundlingEnabled())
496 report_fatal_error(reason: ".bundle_unlock forbidden when bundling is disabled");
497 else if (!isBundleLocked())
498 report_fatal_error(reason: ".bundle_unlock without matching lock");
499 else if (Sec.isBundleGroupBeforeFirstInst())
500 report_fatal_error(reason: "Empty bundle-locked group is forbidden");
501
502 Sec.setBundleLockState(MCSection::NotBundleLocked);
503}
504
505void MCELFStreamer::finishImpl() {
506 // Emit the .gnu attributes section if any attributes have been added.
507 if (!GNUAttributes.empty()) {
508 MCSection *DummyAttributeSection = nullptr;
509 createAttributesSection(Vendor: "gnu", Section: ".gnu.attributes", Type: ELF::SHT_GNU_ATTRIBUTES,
510 AttributeSection&: DummyAttributeSection, AttrsVec&: GNUAttributes);
511 }
512
513 // Ensure the last section gets aligned if necessary.
514 if (MCFragment *F = getCurrentFragment())
515 setSectionAlignmentForBundling(Assembler: getAssembler(), Section: F->getParent());
516
517 finalizeCGProfile();
518 emitFrames(MAB: nullptr);
519
520 this->MCObjectStreamer::finishImpl();
521}
522
523void 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(Elt: Item);
538}
539
540void 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(Elt: Item);
555}
556
557void 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(Elt: Item);
574}
575
576MCELFStreamer::AttributeItem *
577MCELFStreamer::getAttributeItem(unsigned Attribute) {
578 for (AttributeItem &Item : Contents)
579 if (Item.Tag == Attribute)
580 return &Item;
581 return nullptr;
582}
583
584size_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(Value: Item.Tag);
593 Result += getULEB128Size(Value: Item.IntValue);
594 break;
595 case AttributeItem::TextAttribute:
596 Result += getULEB128Size(Value: Item.Tag);
597 Result += Item.StringValue.size() + 1; // string + '\0'
598 break;
599 case AttributeItem::NumericAndTextAttributes:
600 Result += getULEB128Size(Value: Item.Tag);
601 Result += getULEB128Size(Value: Item.IntValue);
602 Result += Item.StringValue.size() + 1; // string + '\0';
603 break;
604 }
605 }
606 return Result;
607}
608
609void 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(Section: AttributeSection);
623 } else {
624 AttributeSection = getContext().getELFSection(Section, Type, Flags: 0);
625 switchSection(Section: AttributeSection);
626
627 // Format version
628 emitInt8(Value: 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(Value: VendorHeaderSize + TagHeaderSize + ContentsSize);
640 emitBytes(Data: Vendor);
641 emitInt8(Value: 0); // '\0'
642
643 emitInt8(Value: ARMBuildAttrs::File);
644 emitInt32(Value: 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(Value: Item.Tag);
650 switch (Item.Type) {
651 default:
652 llvm_unreachable("Invalid attribute type");
653 case AttributeItem::NumericAttribute:
654 emitULEB128IntValue(Value: Item.IntValue);
655 break;
656 case AttributeItem::TextAttribute:
657 emitBytes(Data: Item.StringValue);
658 emitInt8(Value: 0); // '\0'
659 break;
660 case AttributeItem::NumericAndTextAttributes:
661 emitULEB128IntValue(Value: Item.IntValue);
662 emitBytes(Data: Item.StringValue);
663 emitInt8(Value: 0); // '\0'
664 break;
665 }
666 }
667
668 AttrsVec.clear();
669}
670
671void 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(Section: AttributeSection);
687 } else {
688 AttributeSection = getContext().getELFSection(Section, Type, Flags: 0);
689 switchSection(Section: AttributeSection);
690
691 // Format version
692 emitInt8(Value: 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(AttrsVec&: SubSection.Content);
701
702 emitInt32(Value: VendorHeaderSize + VendorParameters + ContentsSize);
703 emitBytes(Data: SubSection.VendorName);
704 emitInt8(Value: 0); // '\0'
705 emitInt8(Value: SubSection.IsOptional);
706 emitInt8(Value: SubSection.ParameterType);
707
708 for (AttributeItem &Item : SubSection.Content) {
709 emitULEB128IntValue(Value: Item.Tag);
710 switch (Item.Type) {
711 default:
712 assert(0 && "Invalid attribute type");
713 break;
714 case AttributeItem::NumericAttribute:
715 emitULEB128IntValue(Value: Item.IntValue);
716 break;
717 case AttributeItem::TextAttribute:
718 emitBytes(Data: Item.StringValue);
719 emitInt8(Value: 0); // '\0'
720 break;
721 case AttributeItem::NumericAndTextAttributes:
722 emitULEB128IntValue(Value: Item.IntValue);
723 emitBytes(Data: Item.StringValue);
724 emitInt8(Value: 0); // '\0'
725 break;
726 }
727 }
728 }
729 SubSectionVec.clear();
730}
731
732MCStreamer *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