LLVM 22.0.0git
ELFAsmParser.cpp
Go to the documentation of this file.
1//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
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
11#include "llvm/ADT/StringRef.h"
14#include "llvm/MC/MCAsmInfo.h"
15#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCStreamer.h"
22#include "llvm/MC/MCSymbol.h"
23#include "llvm/MC/MCSymbolELF.h"
24#include "llvm/MC/SectionKind.h"
25#include "llvm/Support/SMLoc.h"
26#include <cassert>
27#include <cstdint>
28#include <utility>
29
30using namespace llvm;
31
32namespace {
33
34class ELFAsmParser : public MCAsmParserExtension {
35 template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
36 void addDirectiveHandler(StringRef Directive) {
37 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
38 this, HandleDirective<ELFAsmParser, HandlerMethod>);
39
40 getParser().addDirectiveHandler(Directive, Handler);
41 }
42
43 bool parseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
44 SectionKind Kind);
45
46public:
47 ELFAsmParser() { BracketExpressionsSupported = true; }
48
49 void Initialize(MCAsmParser &Parser) override {
50 // Call the base implementation.
52
53 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveData>(".data");
54 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveText>(".text");
55 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveBSS>(".bss");
56 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveRoData>(".rodata");
57 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveTData>(".tdata");
58 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveTBSS>(".tbss");
59 addDirectiveHandler<&ELFAsmParser::parseDirectiveSection>(".section");
60 addDirectiveHandler<
61 &ELFAsmParser::parseDirectivePushSection>(".pushsection");
62 addDirectiveHandler<&ELFAsmParser::parseDirectivePopSection>(".popsection");
63 addDirectiveHandler<&ELFAsmParser::parseDirectiveSize>(".size");
64 addDirectiveHandler<&ELFAsmParser::parseDirectivePrevious>(".previous");
65 addDirectiveHandler<&ELFAsmParser::parseDirectiveType>(".type");
66 addDirectiveHandler<&ELFAsmParser::parseDirectiveIdent>(".ident");
67 addDirectiveHandler<&ELFAsmParser::parseDirectiveSymver>(".symver");
68 addDirectiveHandler<&ELFAsmParser::parseDirectiveVersion>(".version");
69 addDirectiveHandler<&ELFAsmParser::parseDirectiveWeakref>(".weakref");
70 addDirectiveHandler<&ELFAsmParser::parseDirectiveSymbolAttribute>(".weak");
71 addDirectiveHandler<&ELFAsmParser::parseDirectiveSymbolAttribute>(".local");
72 addDirectiveHandler<
73 &ELFAsmParser::parseDirectiveSymbolAttribute>(".protected");
74 addDirectiveHandler<
75 &ELFAsmParser::parseDirectiveSymbolAttribute>(".internal");
76 addDirectiveHandler<
77 &ELFAsmParser::parseDirectiveSymbolAttribute>(".hidden");
78 addDirectiveHandler<&ELFAsmParser::parseDirectiveSubsection>(".subsection");
79 addDirectiveHandler<&ELFAsmParser::parseDirectiveCGProfile>(".cg_profile");
80 }
81
82 // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
83 // the best way for us to get access to it?
84 bool parseSectionDirectiveData(StringRef, SMLoc) {
85 return parseSectionSwitch(".data", ELF::SHT_PROGBITS,
88 }
89 bool parseSectionDirectiveText(StringRef, SMLoc) {
90 return parseSectionSwitch(".text", ELF::SHT_PROGBITS,
93 }
94 bool parseSectionDirectiveBSS(StringRef, SMLoc) {
95 return parseSectionSwitch(".bss", ELF::SHT_NOBITS,
98 }
99 bool parseSectionDirectiveRoData(StringRef, SMLoc) {
100 return parseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
103 }
104 bool parseSectionDirectiveTData(StringRef, SMLoc) {
105 return parseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
109 }
110 bool parseSectionDirectiveTBSS(StringRef, SMLoc) {
111 return parseSectionSwitch(".tbss", ELF::SHT_NOBITS,
115 }
116 bool parseDirectivePushSection(StringRef, SMLoc);
117 bool parseDirectivePopSection(StringRef, SMLoc);
118 bool parseDirectiveSection(StringRef, SMLoc);
119 bool parseDirectiveSize(StringRef, SMLoc);
120 bool parseDirectivePrevious(StringRef, SMLoc);
121 bool parseDirectiveType(StringRef, SMLoc);
122 bool parseDirectiveIdent(StringRef, SMLoc);
123 bool parseDirectiveSymver(StringRef, SMLoc);
124 bool parseDirectiveVersion(StringRef, SMLoc);
125 bool parseDirectiveWeakref(StringRef, SMLoc);
126 bool parseDirectiveSymbolAttribute(StringRef, SMLoc);
127 bool parseDirectiveSubsection(StringRef, SMLoc);
128 bool parseDirectiveCGProfile(StringRef, SMLoc);
129
130private:
131 bool parseSectionName(StringRef &SectionName);
132 bool parseSectionArguments(bool IsPush, SMLoc loc);
133 unsigned parseSunStyleSectionFlags();
134 bool maybeParseSectionType(StringRef &TypeName);
135 bool parseMergeSize(int64_t &Size);
136 bool parseGroup(StringRef &GroupName, bool &IsComdat);
137 bool parseLinkedToSym(MCSymbolELF *&LinkedToSym);
138};
139
140} // end anonymous namespace
141
142/// parseDirectiveSymbolAttribute
143/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
144bool ELFAsmParser::parseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
145 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
146 .Case(".weak", MCSA_Weak)
147 .Case(".local", MCSA_Local)
148 .Case(".hidden", MCSA_Hidden)
149 .Case(".internal", MCSA_Internal)
150 .Case(".protected", MCSA_Protected)
151 .Default(MCSA_Invalid);
152 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
153 if (getLexer().isNot(AsmToken::EndOfStatement)) {
154 while (true) {
155 StringRef Name;
156
157 if (getParser().parseIdentifier(Name))
158 return TokError("expected identifier");
159
160 if (getParser().discardLTOSymbol(Name)) {
161 if (getLexer().is(AsmToken::EndOfStatement))
162 break;
163 continue;
164 }
165
166 MCSymbol *Sym = getContext().parseSymbol(Name);
167
168 getStreamer().emitSymbolAttribute(Sym, Attr);
169
170 if (getLexer().is(AsmToken::EndOfStatement))
171 break;
172
173 if (getLexer().isNot(AsmToken::Comma))
174 return TokError("expected comma");
175 Lex();
176 }
177 }
178
179 Lex();
180 return false;
181}
182
183bool ELFAsmParser::parseSectionSwitch(StringRef Section, unsigned Type,
184 unsigned Flags, SectionKind Kind) {
185 const MCExpr *Subsection = nullptr;
186 if (getLexer().isNot(AsmToken::EndOfStatement)) {
187 if (getParser().parseExpression(Subsection))
188 return true;
189 }
190 Lex();
191
192 getStreamer().switchSection(getContext().getELFSection(Section, Type, Flags),
193 Subsection);
194
195 return false;
196}
197
198bool ELFAsmParser::parseDirectiveSize(StringRef, SMLoc) {
199 MCSymbol *Sym;
200 if (getParser().parseSymbol(Sym))
201 return TokError("expected identifier");
202
203 if (getLexer().isNot(AsmToken::Comma))
204 return TokError("expected comma");
205 Lex();
206
207 const MCExpr *Expr;
208 if (getParser().parseExpression(Expr))
209 return true;
210
211 if (getLexer().isNot(AsmToken::EndOfStatement))
212 return TokError("unexpected token");
213 Lex();
214
215 getStreamer().emitELFSize(Sym, Expr);
216 return false;
217}
218
219bool ELFAsmParser::parseSectionName(StringRef &SectionName) {
220 // A section name can contain -, so we cannot just use
221 // parseIdentifier.
222 SMLoc FirstLoc = getLexer().getLoc();
223 unsigned Size = 0;
224
225 if (getLexer().is(AsmToken::String)) {
226 SectionName = getTok().getIdentifier();
227 Lex();
228 return false;
229 }
230
231 while (!getParser().hasPendingError()) {
232 SMLoc PrevLoc = getLexer().getLoc();
233 if (getLexer().is(AsmToken::Comma) ||
234 getLexer().is(AsmToken::EndOfStatement))
235 break;
236
237 unsigned CurSize;
238 if (getLexer().is(AsmToken::String)) {
239 CurSize = getTok().getIdentifier().size() + 2;
240 Lex();
241 } else if (getLexer().is(AsmToken::Identifier)) {
242 CurSize = getTok().getIdentifier().size();
243 Lex();
244 } else {
245 CurSize = getTok().getString().size();
246 Lex();
247 }
248 Size += CurSize;
249 SectionName = StringRef(FirstLoc.getPointer(), Size);
250
251 // Make sure the following token is adjacent.
252 if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
253 break;
254 }
255 if (Size == 0)
256 return true;
257
258 return false;
259}
260
261static unsigned parseSectionFlags(const Triple &TT, StringRef flagsStr,
262 bool *UseLastGroup) {
263 unsigned flags = 0;
264
265 // If a valid numerical value is set for the section flag, use it verbatim
266 if (!flagsStr.getAsInteger(0, flags))
267 return flags;
268
269 for (char i : flagsStr) {
270 switch (i) {
271 case 'a':
272 flags |= ELF::SHF_ALLOC;
273 break;
274 case 'e':
275 flags |= ELF::SHF_EXCLUDE;
276 break;
277 case 'x':
278 flags |= ELF::SHF_EXECINSTR;
279 break;
280 case 'w':
281 flags |= ELF::SHF_WRITE;
282 break;
283 case 'o':
284 flags |= ELF::SHF_LINK_ORDER;
285 break;
286 case 'M':
287 flags |= ELF::SHF_MERGE;
288 break;
289 case 'S':
290 flags |= ELF::SHF_STRINGS;
291 break;
292 case 'T':
293 flags |= ELF::SHF_TLS;
294 break;
295 case 'c':
296 if (TT.getArch() != Triple::xcore)
297 return -1U;
299 break;
300 case 'd':
301 if (TT.getArch() != Triple::xcore)
302 return -1U;
304 break;
305 case 'y':
306 if (TT.isARM() || TT.isThumb())
307 flags |= ELF::SHF_ARM_PURECODE;
308 else if (TT.isAArch64())
310 else
311 return -1U;
312 break;
313 case 's':
314 if (TT.getArch() != Triple::hexagon)
315 return -1U;
316 flags |= ELF::SHF_HEX_GPREL;
317 break;
318 case 'G':
319 flags |= ELF::SHF_GROUP;
320 break;
321 case 'l':
322 if (TT.getArch() != Triple::x86_64)
323 return -1U;
324 flags |= ELF::SHF_X86_64_LARGE;
325 break;
326 case 'R':
327 if (TT.isOSSolaris())
329 else
330 flags |= ELF::SHF_GNU_RETAIN;
331 break;
332 case '?':
333 *UseLastGroup = true;
334 break;
335 default:
336 return -1U;
337 }
338 }
339
340 return flags;
341}
342
343unsigned ELFAsmParser::parseSunStyleSectionFlags() {
344 unsigned flags = 0;
345 while (getLexer().is(AsmToken::Hash)) {
346 Lex(); // Eat the #.
347
348 if (!getLexer().is(AsmToken::Identifier))
349 return -1U;
350
351 StringRef flagId = getTok().getIdentifier();
352 if (flagId == "alloc")
353 flags |= ELF::SHF_ALLOC;
354 else if (flagId == "execinstr")
355 flags |= ELF::SHF_EXECINSTR;
356 else if (flagId == "write")
357 flags |= ELF::SHF_WRITE;
358 else if (flagId == "tls")
359 flags |= ELF::SHF_TLS;
360 else
361 return -1U;
362
363 Lex(); // Eat the flag.
364
365 if (!getLexer().is(AsmToken::Comma))
366 break;
367 Lex(); // Eat the comma.
368 }
369 return flags;
370}
371
372
373bool ELFAsmParser::parseDirectivePushSection(StringRef s, SMLoc loc) {
374 getStreamer().pushSection();
375
376 if (parseSectionArguments(/*IsPush=*/true, loc)) {
377 getStreamer().popSection();
378 return true;
379 }
380
381 return false;
382}
383
384bool ELFAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
385 if (!getStreamer().popSection())
386 return TokError(".popsection without corresponding .pushsection");
387 return false;
388}
389
390bool ELFAsmParser::parseDirectiveSection(StringRef, SMLoc loc) {
391 return parseSectionArguments(/*IsPush=*/false, loc);
392}
393
394bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {
395 AsmLexer &L = getLexer();
396 if (L.isNot(AsmToken::Comma))
397 return false;
398 Lex();
399 if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) &&
400 L.isNot(AsmToken::String)) {
401 if (getContext().getAsmInfo()->getCommentString().starts_with('@'))
402 return TokError("expected '%<type>' or \"<type>\"");
403 else
404 return TokError("expected '@<type>', '%<type>' or \"<type>\"");
405 }
406 if (!L.is(AsmToken::String))
407 Lex();
408 if (L.is(AsmToken::Integer)) {
409 TypeName = getTok().getString();
410 Lex();
411 } else if (getParser().parseIdentifier(TypeName))
412 return TokError("expected identifier");
413 return false;
414}
415
416bool ELFAsmParser::parseMergeSize(int64_t &Size) {
417 if (getLexer().isNot(AsmToken::Comma))
418 return TokError("expected the entry size");
419 Lex();
420 if (getParser().parseAbsoluteExpression(Size))
421 return true;
422 if (Size <= 0)
423 return TokError("entry size must be positive");
424 return false;
425}
426
427bool ELFAsmParser::parseGroup(StringRef &GroupName, bool &IsComdat) {
428 AsmLexer &L = getLexer();
429 if (L.isNot(AsmToken::Comma))
430 return TokError("expected group name");
431 Lex();
432 if (L.is(AsmToken::Integer)) {
433 GroupName = getTok().getString();
434 Lex();
435 } else if (getParser().parseIdentifier(GroupName)) {
436 return TokError("invalid group name");
437 }
438 if (L.is(AsmToken::Comma)) {
439 Lex();
440 StringRef Linkage;
441 if (getParser().parseIdentifier(Linkage))
442 return TokError("invalid linkage");
443 if (Linkage != "comdat")
444 return TokError("Linkage must be 'comdat'");
445 IsComdat = true;
446 } else {
447 IsComdat = false;
448 }
449 return false;
450}
451
452bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) {
453 AsmLexer &L = getLexer();
454 if (L.isNot(AsmToken::Comma))
455 return TokError("expected linked-to symbol");
456 Lex();
457 StringRef Name;
458 SMLoc StartLoc = L.getLoc();
459 if (getParser().parseIdentifier(Name)) {
460 if (getParser().getTok().getString() == "0") {
461 getParser().Lex();
462 LinkedToSym = nullptr;
463 return false;
464 }
465 return TokError("invalid linked-to symbol");
466 }
467 LinkedToSym = static_cast<MCSymbolELF *>(getContext().lookupSymbol(Name));
468 if (!LinkedToSym || !LinkedToSym->isInSection())
469 return Error(StartLoc, "linked-to symbol is not in a section: " + Name);
470 return false;
471}
472
474 return SectionName.consume_front(Prefix) &&
475 (SectionName.empty() || SectionName[0] == '.');
476}
477
479 unsigned Type) {
480 if (TT.getArch() == Triple::x86_64) {
481 // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,
482 // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't
483 // error for SHT_PROGBITS .eh_frame
484 return SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS;
485 }
486 if (TT.isMIPS()) {
487 // MIPS .debug_* sections should have SHT_MIPS_DWARF section type to
488 // distinguish among sections contain DWARF and ECOFF debug formats,
489 // but in assembly files these sections have SHT_PROGBITS type.
490 return SectionName.starts_with(".debug_") && Type == ELF::SHT_PROGBITS;
491 }
492 return false;
493}
494
495bool ELFAsmParser::parseSectionArguments(bool IsPush, SMLoc loc) {
496 StringRef SectionName;
497
498 if (parseSectionName(SectionName))
499 return TokError("expected identifier");
500
501 StringRef TypeName;
502 int64_t Size = 0;
503 StringRef GroupName;
504 bool IsComdat = false;
505 unsigned Flags = 0;
506 unsigned extraFlags = 0;
507 const MCExpr *Subsection = nullptr;
508 bool UseLastGroup = false;
509 MCSymbolELF *LinkedToSym = nullptr;
510 int64_t UniqueID = ~0;
511
512 // Set the defaults first.
513 if (hasPrefix(SectionName, ".rodata") || SectionName == ".rodata1")
515 else if (SectionName == ".fini" || SectionName == ".init" ||
516 hasPrefix(SectionName, ".text"))
518 else if (hasPrefix(SectionName, ".data") || SectionName == ".data1" ||
519 hasPrefix(SectionName, ".bss") ||
520 hasPrefix(SectionName, ".init_array") ||
521 hasPrefix(SectionName, ".fini_array") ||
522 hasPrefix(SectionName, ".preinit_array"))
524 else if (hasPrefix(SectionName, ".tdata") || hasPrefix(SectionName, ".tbss"))
526
527 if (getLexer().is(AsmToken::Comma)) {
528 Lex();
529
530 if (IsPush && getLexer().isNot(AsmToken::String)) {
531 if (getParser().parseExpression(Subsection))
532 return true;
533 if (getLexer().isNot(AsmToken::Comma))
534 goto EndStmt;
535 Lex();
536 }
537
538 if (getLexer().isNot(AsmToken::String)) {
539 if (getLexer().isNot(AsmToken::Hash))
540 return TokError("expected string");
541 extraFlags = parseSunStyleSectionFlags();
542 } else {
543 StringRef FlagsStr = getTok().getStringContents();
544 Lex();
545 extraFlags = parseSectionFlags(getContext().getTargetTriple(), FlagsStr,
546 &UseLastGroup);
547 }
548
549 if (extraFlags == -1U)
550 return TokError("unknown flag");
551 Flags |= extraFlags;
552
553 bool Mergeable = Flags & ELF::SHF_MERGE;
554 bool Group = Flags & ELF::SHF_GROUP;
555 if (Group && UseLastGroup)
556 return TokError("Section cannot specifiy a group name while also acting "
557 "as a member of the last group");
558
559 if (maybeParseSectionType(TypeName))
560 return true;
561
562 AsmLexer &L = getLexer();
563 if (TypeName.empty()) {
564 if (Mergeable)
565 return TokError("Mergeable section must specify the type");
566 if (Group)
567 return TokError("Group section must specify the type");
568 if (L.isNot(AsmToken::EndOfStatement))
569 return TokError("expected end of directive");
570 }
571
572 if (Mergeable || TypeName == "llvm_cfi_jump_table")
573 if (parseMergeSize(Size))
574 return true;
575 if (Flags & ELF::SHF_LINK_ORDER)
576 if (parseLinkedToSym(LinkedToSym))
577 return true;
578 if (Group)
579 if (parseGroup(GroupName, IsComdat))
580 return true;
581 if (maybeParseUniqueID(UniqueID))
582 return true;
583 }
584
585EndStmt:
586 if (getLexer().isNot(AsmToken::EndOfStatement))
587 return TokError("expected end of directive");
588 Lex();
589
590 unsigned Type = ELF::SHT_PROGBITS;
591
592 if (TypeName.empty()) {
593 if (SectionName.starts_with(".note"))
595 else if (hasPrefix(SectionName, ".init_array"))
597 else if (hasPrefix(SectionName, ".bss"))
599 else if (hasPrefix(SectionName, ".tbss"))
601 else if (hasPrefix(SectionName, ".fini_array"))
603 else if (hasPrefix(SectionName, ".preinit_array"))
605 } else {
606 if (TypeName == "init_array")
608 else if (TypeName == "fini_array")
610 else if (TypeName == "preinit_array")
612 else if (TypeName == "nobits")
614 else if (TypeName == "progbits")
616 else if (TypeName == "note")
618 else if (TypeName == "unwind")
620 else if (TypeName == "llvm_odrtab")
622 else if (TypeName == "llvm_linker_options")
624 else if (TypeName == "llvm_call_graph_profile")
626 else if (TypeName == "llvm_dependent_libraries")
628 else if (TypeName == "llvm_sympart")
630 else if (TypeName == "llvm_bb_addr_map")
632 else if (TypeName == "llvm_offloading")
634 else if (TypeName == "llvm_lto")
636 else if (TypeName == "llvm_jt_sizes")
638 else if (TypeName == "llvm_cfi_jump_table")
640 else if (TypeName.getAsInteger(0, Type))
641 return TokError("unknown section type");
642 }
643
644 if (UseLastGroup) {
645 if (auto *Section = static_cast<const MCSectionELF *>(
646 getStreamer().getCurrentSectionOnly()))
647 if (const MCSymbol *Group = Section->getGroup()) {
648 GroupName = Group->getName();
649 IsComdat = Section->isComdat();
651 }
652 }
653
654 MCSectionELF *Section =
655 getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,
656 IsComdat, UniqueID, LinkedToSym);
657 getStreamer().switchSection(Section, Subsection);
658 // Check that flags are used consistently. However, the GNU assembler permits
659 // to leave out in subsequent uses of the same sections; for compatibility,
660 // do likewise.
661 if (!TypeName.empty() && Section->getType() != Type &&
662 !allowSectionTypeMismatch(getContext().getTargetTriple(), SectionName,
663 Type))
664 Error(loc, "changed section type for " + SectionName + ", expected: 0x" +
665 utohexstr(Section->getType()));
666 if ((extraFlags || Size || !TypeName.empty()) && Section->getFlags() != Flags)
667 Error(loc, "changed section flags for " + SectionName + ", expected: 0x" +
668 utohexstr(Section->getFlags()));
669 if ((extraFlags || Size || !TypeName.empty()) &&
670 Section->getEntrySize() != Size)
671 Error(loc, "changed section entsize for " + SectionName +
672 ", expected: " + Twine(Section->getEntrySize()));
673
674 if (getContext().getGenDwarfForAssembly() &&
675 (Section->getFlags() & ELF::SHF_ALLOC) &&
676 (Section->getFlags() & ELF::SHF_EXECINSTR)) {
677 bool InsertResult = getContext().addGenDwarfSection(Section);
678 if (InsertResult && getContext().getDwarfVersion() <= 2)
679 Warning(loc, "DWARF2 only supports one section per compilation unit");
680 }
681
682 return false;
683}
684
685bool ELFAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {
686 MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
687 if (PreviousSection.first == nullptr)
688 return TokError(".previous without corresponding .section");
689 getStreamer().switchSection(PreviousSection.first, PreviousSection.second);
690
691 return false;
692}
693
696 .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
697 .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
698 .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
699 .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
700 .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
701 .Cases("STT_GNU_IFUNC", "gnu_indirect_function",
703 .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
705}
706
707/// parseDirectiveELFType
708/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
709/// ::= .type identifier , #attribute
710/// ::= .type identifier , @attribute
711/// ::= .type identifier , %attribute
712/// ::= .type identifier , "attribute"
713bool ELFAsmParser::parseDirectiveType(StringRef, SMLoc) {
714 MCSymbol *Sym;
715 if (getParser().parseSymbol(Sym))
716 return TokError("expected identifier");
717
718 bool AllowAt = getLexer().getAllowAtInIdentifier();
719 if (!AllowAt &&
720 !getContext().getAsmInfo()->getCommentString().starts_with("@"))
721 getLexer().setAllowAtInIdentifier(true);
722 auto _ =
723 make_scope_exit([&]() { getLexer().setAllowAtInIdentifier(AllowAt); });
724
725 // NOTE the comma is optional in all cases. It is only documented as being
726 // optional in the first case, however, GAS will silently treat the comma as
727 // optional in all cases. Furthermore, although the documentation states that
728 // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
729 // accepts both the upper case name as well as the lower case aliases.
730 if (getLexer().is(AsmToken::Comma))
731 Lex();
732
733 if (getLexer().isNot(AsmToken::Identifier) &&
734 getLexer().isNot(AsmToken::Hash) &&
735 getLexer().isNot(AsmToken::Percent) &&
736 getLexer().isNot(AsmToken::String)) {
737 if (!getLexer().getAllowAtInIdentifier())
738 return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
739 "'%<type>' or \"<type>\"");
740 else if (getLexer().isNot(AsmToken::At))
741 return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
742 "'%<type>' or \"<type>\"");
743 }
744
745 if (getLexer().isNot(AsmToken::String) &&
746 getLexer().isNot(AsmToken::Identifier))
747 Lex();
748
749 SMLoc TypeLoc = getLexer().getLoc();
750
751 StringRef Type;
752 if (getParser().parseIdentifier(Type))
753 return TokError("expected symbol type");
754
756 if (Attr == MCSA_Invalid)
757 return Error(TypeLoc, "unsupported attribute");
758
759 if (getLexer().isNot(AsmToken::EndOfStatement))
760 return TokError("expected end of directive");
761 Lex();
762
763 getStreamer().emitSymbolAttribute(Sym, Attr);
764
765 return false;
766}
767
768/// parseDirectiveIdent
769/// ::= .ident string
770bool ELFAsmParser::parseDirectiveIdent(StringRef, SMLoc) {
771 if (getLexer().isNot(AsmToken::String))
772 return TokError("expected string");
773
774 StringRef Data = getTok().getIdentifier();
775
776 Lex();
777
778 if (getLexer().isNot(AsmToken::EndOfStatement))
779 return TokError("expected end of directive");
780 Lex();
781
782 getStreamer().emitIdent(Data);
783 return false;
784}
785
786/// parseDirectiveSymver
787/// ::= .symver foo, bar2@zed
788bool ELFAsmParser::parseDirectiveSymver(StringRef, SMLoc) {
789 MCSymbol *OriginalSym;
790 StringRef Name, Action;
791 if (getParser().parseSymbol(OriginalSym))
792 return TokError("expected identifier");
793
794 if (getLexer().isNot(AsmToken::Comma))
795 return TokError("expected a comma");
796
797 // ARM assembly uses @ for a comment...
798 // except when parsing the second parameter of the .symver directive.
799 // Force the next symbol to allow @ in the identifier, which is
800 // required for this directive and then reset it to its initial state.
801 const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
802 getLexer().setAllowAtInIdentifier(true);
803 Lex();
804 getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
805
806 if (getParser().parseIdentifier(Name))
807 return TokError("expected identifier");
808
809 if (!Name.contains('@'))
810 return TokError("expected a '@' in the name");
811 bool KeepOriginalSym = !Name.contains("@@@");
812 if (parseOptionalToken(AsmToken::Comma)) {
813 if (getParser().parseIdentifier(Action) || Action != "remove")
814 return TokError("expected 'remove'");
815 KeepOriginalSym = false;
816 }
817 (void)parseOptionalToken(AsmToken::EndOfStatement);
818
819 getStreamer().emitELFSymverDirective(OriginalSym, Name, KeepOriginalSym);
820 return false;
821}
822
823/// parseDirectiveVersion
824/// ::= .version string
825bool ELFAsmParser::parseDirectiveVersion(StringRef, SMLoc) {
826 if (getLexer().isNot(AsmToken::String))
827 return TokError("expected string");
828
829 StringRef Data = getTok().getIdentifier();
830
831 Lex();
832
833 MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
834
835 getStreamer().pushSection();
836 getStreamer().switchSection(Note);
837 getStreamer().emitInt32(Data.size() + 1); // namesz
838 getStreamer().emitInt32(0); // descsz = 0 (no description).
839 getStreamer().emitInt32(1); // type = NT_VERSION
840 getStreamer().emitBytes(Data); // name
841 getStreamer().emitInt8(0); // NUL
842 getStreamer().emitValueToAlignment(Align(4));
843 getStreamer().popSection();
844 return false;
845}
846
847/// parseDirectiveWeakref
848/// ::= .weakref foo, bar
849bool ELFAsmParser::parseDirectiveWeakref(StringRef, SMLoc) {
850 // FIXME: Share code with the other alias building directives.
851
852 MCSymbol *Alias;
853 if (getParser().parseSymbol(Alias))
854 return TokError("expected identifier");
855
856 if (getLexer().isNot(AsmToken::Comma))
857 return TokError("expected a comma");
858
859 Lex();
860
861 MCSymbol *Sym;
862 if (getParser().parseSymbol(Sym))
863 return TokError("expected identifier");
864
865 getStreamer().emitWeakReference(Alias, Sym);
866 return false;
867}
868
869bool ELFAsmParser::parseDirectiveSubsection(StringRef, SMLoc) {
870 const MCExpr *Subsection = MCConstantExpr::create(0, getContext());
871 if (getLexer().isNot(AsmToken::EndOfStatement)) {
872 if (getParser().parseExpression(Subsection))
873 return true;
874 }
875
876 if (getLexer().isNot(AsmToken::EndOfStatement))
877 return TokError("expected end of directive");
878
879 Lex();
880
881 return getStreamer().switchSection(getStreamer().getCurrentSectionOnly(),
882 Subsection);
883}
884
885bool ELFAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) {
887}
888
889namespace llvm {
890
892 return new ELFAsmParser;
893}
894
895} // end namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
DXIL Finalize Linkage
static bool allowSectionTypeMismatch(const Triple &TT, StringRef SectionName, unsigned Type)
static unsigned parseSectionFlags(const Triple &TT, StringRef flagsStr, bool *UseLastGroup)
static MCSymbolAttr MCAttrForString(StringRef Type)
#define _
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
static bool hasPrefix(StringRef SectionName, StringRef Prefix)
Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
bool parseDirectiveCGProfile(StringRef, SMLoc)
parseDirectiveCGProfile ::= .cg_profile identifier, identifier, <number>
std::pair< MCAsmParserExtension *, DirectiveHandler > ExtensionDirectiveHandler
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).
Definition MCSymbol.h:237
Represents a location in source code.
Definition SMLoc.h:23
constexpr const char * getPointer() const
Definition SMLoc.h:34
static SectionKind getThreadData()
static SectionKind getText()
static SectionKind getData()
static SectionKind getBSS()
static SectionKind getThreadBSS()
static SectionKind getReadOnly()
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:480
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
const char SectionName[]
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ SHT_LLVM_JT_SIZES
Definition ELF.h:1184
@ SHT_LLVM_DEPENDENT_LIBRARIES
Definition ELF.h:1174
@ SHT_PROGBITS
Definition ELF.h:1143
@ SHT_LLVM_LINKER_OPTIONS
Definition ELF.h:1171
@ SHT_LLVM_CALL_GRAPH_PROFILE
Definition ELF.h:1180
@ SHT_NOBITS
Definition ELF.h:1150
@ SHT_LLVM_ODRTAB
Definition ELF.h:1170
@ SHT_LLVM_OFFLOADING
Definition ELF.h:1182
@ SHT_LLVM_LTO
Definition ELF.h:1183
@ SHT_PREINIT_ARRAY
Definition ELF.h:1156
@ SHT_LLVM_BB_ADDR_MAP
Definition ELF.h:1181
@ SHT_LLVM_CFI_JUMP_TABLE
Definition ELF.h:1185
@ SHT_INIT_ARRAY
Definition ELF.h:1154
@ SHT_NOTE
Definition ELF.h:1149
@ SHT_X86_64_UNWIND
Definition ELF.h:1217
@ SHT_LLVM_SYMPART
Definition ELF.h:1176
@ SHT_FINI_ARRAY
Definition ELF.h:1155
@ XCORE_SHF_DP_SECTION
All sections with the "d" flag are grouped together by the linker to form the data section and the dp...
Definition ELF.h:1292
@ SHF_MERGE
Definition ELF.h:1249
@ SHF_STRINGS
Definition ELF.h:1252
@ SHF_AARCH64_PURECODE
Definition ELF.h:1341
@ XCORE_SHF_CP_SECTION
All sections with the "c" flag are grouped together by the linker to form the constant pool and the c...
Definition ELF.h:1297
@ SHF_EXCLUDE
Definition ELF.h:1277
@ SHF_ALLOC
Definition ELF.h:1243
@ SHF_LINK_ORDER
Definition ELF.h:1258
@ SHF_HEX_GPREL
Definition ELF.h:1310
@ SHF_GROUP
Definition ELF.h:1265
@ SHF_SUNW_NODISCARD
Definition ELF.h:1284
@ SHF_X86_64_LARGE
Definition ELF.h:1306
@ SHF_GNU_RETAIN
Definition ELF.h:1274
@ SHF_WRITE
Definition ELF.h:1240
@ SHF_TLS
Definition ELF.h:1268
@ SHF_ARM_PURECODE
Definition ELF.h:1338
@ SHF_EXECINSTR
Definition ELF.h:1246
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
Definition Symbol.cpp:75
LLVM_ABI int getDwarfVersion()
Context & getContext() const
Definition BasicBlock.h:99
This is an optimization pass for GlobalISel generic memory operations.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
Definition ScopeExit.h:59
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
std::pair< MCSection *, uint32_t > MCSectionSubPair
Definition MCStreamer.h:66
MCAsmParserExtension * createELFAsmParser()
@ MCSA_Local
.local (ELF)
@ MCSA_Protected
.protected (ELF)
@ MCSA_Internal
.internal (ELF)
@ MCSA_ELF_TypeIndFunction
.type _foo, STT_GNU_IFUNC
@ MCSA_ELF_TypeNoType
.type _foo, STT_NOTYPE # aka @notype
@ MCSA_Weak
.weak
@ MCSA_ELF_TypeTLS
.type _foo, STT_TLS # aka @tls_object
@ MCSA_ELF_TypeCommon
.type _foo, STT_COMMON # aka @common
@ MCSA_ELF_TypeObject
.type _foo, STT_OBJECT # aka @object
@ MCSA_ELF_TypeGnuUniqueObject
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
@ MCSA_Invalid
Not a valid directive.