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