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