xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCParser/ELFAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
906c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
100b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
110b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
120b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
230b57cec5SDimitry Andric #include "llvm/MC/SectionKind.h"
240b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
250b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
260b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
270b57cec5SDimitry Andric #include <cassert>
280b57cec5SDimitry Andric #include <cstdint>
290b57cec5SDimitry Andric #include <utility>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace {
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric class ELFAsmParser : public MCAsmParserExtension {
360b57cec5SDimitry Andric   template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
370b57cec5SDimitry Andric   void addDirectiveHandler(StringRef Directive) {
380b57cec5SDimitry Andric     MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
390b57cec5SDimitry Andric         this, HandleDirective<ELFAsmParser, HandlerMethod>);
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric     getParser().addDirectiveHandler(Directive, Handler);
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
450b57cec5SDimitry Andric                           SectionKind Kind);
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric public:
480b57cec5SDimitry Andric   ELFAsmParser() { BracketExpressionsSupported = true; }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   void Initialize(MCAsmParser &Parser) override {
510b57cec5SDimitry Andric     // Call the base implementation.
520b57cec5SDimitry Andric     this->MCAsmParserExtension::Initialize(Parser);
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
550b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
560b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
570b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
580b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
590b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
600b57cec5SDimitry Andric     addDirectiveHandler<
610b57cec5SDimitry Andric       &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
620b57cec5SDimitry Andric     addDirectiveHandler<
630b57cec5SDimitry Andric       &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
640b57cec5SDimitry Andric     addDirectiveHandler<
650b57cec5SDimitry Andric       &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
660b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
670b57cec5SDimitry Andric     addDirectiveHandler<
680b57cec5SDimitry Andric       &ELFAsmParser::ParseDirectivePushSection>(".pushsection");
690b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
700b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
710b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
720b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
730b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
740b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
750b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");
760b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
770b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
780b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
790b57cec5SDimitry Andric     addDirectiveHandler<
800b57cec5SDimitry Andric       &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
810b57cec5SDimitry Andric     addDirectiveHandler<
820b57cec5SDimitry Andric       &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
830b57cec5SDimitry Andric     addDirectiveHandler<
840b57cec5SDimitry Andric       &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
850b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
860b57cec5SDimitry Andric     addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
900b57cec5SDimitry Andric   // the best way for us to get access to it?
910b57cec5SDimitry Andric   bool ParseSectionDirectiveData(StringRef, SMLoc) {
920b57cec5SDimitry Andric     return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
930b57cec5SDimitry Andric                               ELF::SHF_WRITE | ELF::SHF_ALLOC,
940b57cec5SDimitry Andric                               SectionKind::getData());
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric   bool ParseSectionDirectiveText(StringRef, SMLoc) {
970b57cec5SDimitry Andric     return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
980b57cec5SDimitry Andric                               ELF::SHF_EXECINSTR |
990b57cec5SDimitry Andric                               ELF::SHF_ALLOC, SectionKind::getText());
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
1020b57cec5SDimitry Andric     return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
1030b57cec5SDimitry Andric                               ELF::SHF_WRITE |
1040b57cec5SDimitry Andric                               ELF::SHF_ALLOC, SectionKind::getBSS());
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric   bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
1070b57cec5SDimitry Andric     return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
1080b57cec5SDimitry Andric                               ELF::SHF_ALLOC,
1090b57cec5SDimitry Andric                               SectionKind::getReadOnly());
1100b57cec5SDimitry Andric   }
1110b57cec5SDimitry Andric   bool ParseSectionDirectiveTData(StringRef, SMLoc) {
1120b57cec5SDimitry Andric     return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
1130b57cec5SDimitry Andric                               ELF::SHF_ALLOC |
1140b57cec5SDimitry Andric                               ELF::SHF_TLS | ELF::SHF_WRITE,
1150b57cec5SDimitry Andric                               SectionKind::getThreadData());
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric   bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
1180b57cec5SDimitry Andric     return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
1190b57cec5SDimitry Andric                               ELF::SHF_ALLOC |
1200b57cec5SDimitry Andric                               ELF::SHF_TLS | ELF::SHF_WRITE,
1210b57cec5SDimitry Andric                               SectionKind::getThreadBSS());
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric   bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
1240b57cec5SDimitry Andric     return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
1250b57cec5SDimitry Andric                               ELF::SHF_ALLOC | ELF::SHF_WRITE,
1260b57cec5SDimitry Andric                               SectionKind::getData());
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric   bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
1290b57cec5SDimitry Andric     return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
1300b57cec5SDimitry Andric                               ELF::SHF_ALLOC |
1310b57cec5SDimitry Andric                               ELF::SHF_WRITE,
1320b57cec5SDimitry Andric                               SectionKind::getReadOnlyWithRel());
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric   bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
1350b57cec5SDimitry Andric     return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
1360b57cec5SDimitry Andric                               ELF::SHF_ALLOC | ELF::SHF_WRITE,
1370b57cec5SDimitry Andric                               SectionKind::getData());
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric   bool ParseDirectivePushSection(StringRef, SMLoc);
1400b57cec5SDimitry Andric   bool ParseDirectivePopSection(StringRef, SMLoc);
1410b57cec5SDimitry Andric   bool ParseDirectiveSection(StringRef, SMLoc);
1420b57cec5SDimitry Andric   bool ParseDirectiveSize(StringRef, SMLoc);
1430b57cec5SDimitry Andric   bool ParseDirectivePrevious(StringRef, SMLoc);
1440b57cec5SDimitry Andric   bool ParseDirectiveType(StringRef, SMLoc);
1450b57cec5SDimitry Andric   bool ParseDirectiveIdent(StringRef, SMLoc);
1460b57cec5SDimitry Andric   bool ParseDirectiveSymver(StringRef, SMLoc);
1470b57cec5SDimitry Andric   bool ParseDirectiveVersion(StringRef, SMLoc);
1480b57cec5SDimitry Andric   bool ParseDirectiveWeakref(StringRef, SMLoc);
1490b57cec5SDimitry Andric   bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
1500b57cec5SDimitry Andric   bool ParseDirectiveSubsection(StringRef, SMLoc);
1510b57cec5SDimitry Andric   bool ParseDirectiveCGProfile(StringRef, SMLoc);
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric private:
1540b57cec5SDimitry Andric   bool ParseSectionName(StringRef &SectionName);
1550b57cec5SDimitry Andric   bool ParseSectionArguments(bool IsPush, SMLoc loc);
1560b57cec5SDimitry Andric   unsigned parseSunStyleSectionFlags();
1570b57cec5SDimitry Andric   bool maybeParseSectionType(StringRef &TypeName);
1580b57cec5SDimitry Andric   bool parseMergeSize(int64_t &Size);
159fe6060f1SDimitry Andric   bool parseGroup(StringRef &GroupName, bool &IsComdat);
1605ffd83dbSDimitry Andric   bool parseLinkedToSym(MCSymbolELF *&LinkedToSym);
1610b57cec5SDimitry Andric   bool maybeParseUniqueID(int64_t &UniqueID);
1620b57cec5SDimitry Andric };
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric } // end anonymous namespace
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric /// ParseDirectiveSymbolAttribute
1670b57cec5SDimitry Andric ///  ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
1680b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
1690b57cec5SDimitry Andric   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
1700b57cec5SDimitry Andric     .Case(".weak", MCSA_Weak)
1710b57cec5SDimitry Andric     .Case(".local", MCSA_Local)
1720b57cec5SDimitry Andric     .Case(".hidden", MCSA_Hidden)
1730b57cec5SDimitry Andric     .Case(".internal", MCSA_Internal)
1740b57cec5SDimitry Andric     .Case(".protected", MCSA_Protected)
1750b57cec5SDimitry Andric     .Default(MCSA_Invalid);
1760b57cec5SDimitry Andric   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
1770b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1780b57cec5SDimitry Andric     while (true) {
1790b57cec5SDimitry Andric       StringRef Name;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric       if (getParser().parseIdentifier(Name))
182bdd1243dSDimitry Andric         return TokError("expected identifier");
1830b57cec5SDimitry Andric 
184fe6060f1SDimitry Andric       if (getParser().discardLTOSymbol(Name)) {
185fe6060f1SDimitry Andric         if (getLexer().is(AsmToken::EndOfStatement))
186fe6060f1SDimitry Andric           break;
187fe6060f1SDimitry Andric         continue;
188fe6060f1SDimitry Andric       }
189fe6060f1SDimitry Andric 
1900b57cec5SDimitry Andric       MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
1910b57cec5SDimitry Andric 
1925ffd83dbSDimitry Andric       getStreamer().emitSymbolAttribute(Sym, Attr);
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric       if (getLexer().is(AsmToken::EndOfStatement))
1950b57cec5SDimitry Andric         break;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric       if (getLexer().isNot(AsmToken::Comma))
198bdd1243dSDimitry Andric         return TokError("expected comma");
1990b57cec5SDimitry Andric       Lex();
2000b57cec5SDimitry Andric     }
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   Lex();
2040b57cec5SDimitry Andric   return false;
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
2080b57cec5SDimitry Andric                                       unsigned Flags, SectionKind Kind) {
2090b57cec5SDimitry Andric   const MCExpr *Subsection = nullptr;
2100b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
2110b57cec5SDimitry Andric     if (getParser().parseExpression(Subsection))
2120b57cec5SDimitry Andric       return true;
2130b57cec5SDimitry Andric   }
2140b57cec5SDimitry Andric   Lex();
2150b57cec5SDimitry Andric 
21681ad6265SDimitry Andric   getStreamer().switchSection(getContext().getELFSection(Section, Type, Flags),
2170b57cec5SDimitry Andric                               Subsection);
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   return false;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
2230b57cec5SDimitry Andric   StringRef Name;
2240b57cec5SDimitry Andric   if (getParser().parseIdentifier(Name))
225bdd1243dSDimitry Andric     return TokError("expected identifier");
2260b57cec5SDimitry Andric   MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
229bdd1243dSDimitry Andric     return TokError("expected comma");
2300b57cec5SDimitry Andric   Lex();
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   const MCExpr *Expr;
2330b57cec5SDimitry Andric   if (getParser().parseExpression(Expr))
2340b57cec5SDimitry Andric     return true;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
237bdd1243dSDimitry Andric     return TokError("unexpected token");
2380b57cec5SDimitry Andric   Lex();
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   getStreamer().emitELFSize(Sym, Expr);
2410b57cec5SDimitry Andric   return false;
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
2450b57cec5SDimitry Andric   // A section name can contain -, so we cannot just use
2460b57cec5SDimitry Andric   // parseIdentifier.
2470b57cec5SDimitry Andric   SMLoc FirstLoc = getLexer().getLoc();
2480b57cec5SDimitry Andric   unsigned Size = 0;
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   if (getLexer().is(AsmToken::String)) {
2510b57cec5SDimitry Andric     SectionName = getTok().getIdentifier();
2520b57cec5SDimitry Andric     Lex();
2530b57cec5SDimitry Andric     return false;
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   while (!getParser().hasPendingError()) {
2570b57cec5SDimitry Andric     SMLoc PrevLoc = getLexer().getLoc();
2580b57cec5SDimitry Andric     if (getLexer().is(AsmToken::Comma) ||
2590b57cec5SDimitry Andric       getLexer().is(AsmToken::EndOfStatement))
2600b57cec5SDimitry Andric       break;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric     unsigned CurSize;
2630b57cec5SDimitry Andric     if (getLexer().is(AsmToken::String)) {
2640b57cec5SDimitry Andric       CurSize = getTok().getIdentifier().size() + 2;
2650b57cec5SDimitry Andric       Lex();
2660b57cec5SDimitry Andric     } else if (getLexer().is(AsmToken::Identifier)) {
2670b57cec5SDimitry Andric       CurSize = getTok().getIdentifier().size();
2680b57cec5SDimitry Andric       Lex();
2690b57cec5SDimitry Andric     } else {
2700b57cec5SDimitry Andric       CurSize = getTok().getString().size();
2710b57cec5SDimitry Andric       Lex();
2720b57cec5SDimitry Andric     }
2730b57cec5SDimitry Andric     Size += CurSize;
2740b57cec5SDimitry Andric     SectionName = StringRef(FirstLoc.getPointer(), Size);
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     // Make sure the following token is adjacent.
2770b57cec5SDimitry Andric     if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
2780b57cec5SDimitry Andric       break;
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric   if (Size == 0)
2810b57cec5SDimitry Andric     return true;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   return false;
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
28681ad6265SDimitry Andric static unsigned parseSectionFlags(const Triple &TT, StringRef flagsStr,
28781ad6265SDimitry Andric                                   bool *UseLastGroup) {
2880b57cec5SDimitry Andric   unsigned flags = 0;
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   // If a valid numerical value is set for the section flag, use it verbatim
2910b57cec5SDimitry Andric   if (!flagsStr.getAsInteger(0, flags))
2920b57cec5SDimitry Andric     return flags;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   for (char i : flagsStr) {
2950b57cec5SDimitry Andric     switch (i) {
2960b57cec5SDimitry Andric     case 'a':
2970b57cec5SDimitry Andric       flags |= ELF::SHF_ALLOC;
2980b57cec5SDimitry Andric       break;
2990b57cec5SDimitry Andric     case 'e':
3000b57cec5SDimitry Andric       flags |= ELF::SHF_EXCLUDE;
3010b57cec5SDimitry Andric       break;
3020b57cec5SDimitry Andric     case 'x':
3030b57cec5SDimitry Andric       flags |= ELF::SHF_EXECINSTR;
3040b57cec5SDimitry Andric       break;
3050b57cec5SDimitry Andric     case 'w':
3060b57cec5SDimitry Andric       flags |= ELF::SHF_WRITE;
3070b57cec5SDimitry Andric       break;
3080b57cec5SDimitry Andric     case 'o':
3090b57cec5SDimitry Andric       flags |= ELF::SHF_LINK_ORDER;
3100b57cec5SDimitry Andric       break;
3110b57cec5SDimitry Andric     case 'M':
3120b57cec5SDimitry Andric       flags |= ELF::SHF_MERGE;
3130b57cec5SDimitry Andric       break;
3140b57cec5SDimitry Andric     case 'S':
3150b57cec5SDimitry Andric       flags |= ELF::SHF_STRINGS;
3160b57cec5SDimitry Andric       break;
3170b57cec5SDimitry Andric     case 'T':
3180b57cec5SDimitry Andric       flags |= ELF::SHF_TLS;
3190b57cec5SDimitry Andric       break;
3200b57cec5SDimitry Andric     case 'c':
32106c3fb27SDimitry Andric       if (TT.getArch() != Triple::xcore)
32206c3fb27SDimitry Andric         return -1U;
3230b57cec5SDimitry Andric       flags |= ELF::XCORE_SHF_CP_SECTION;
3240b57cec5SDimitry Andric       break;
3250b57cec5SDimitry Andric     case 'd':
32606c3fb27SDimitry Andric       if (TT.getArch() != Triple::xcore)
32706c3fb27SDimitry Andric         return -1U;
3280b57cec5SDimitry Andric       flags |= ELF::XCORE_SHF_DP_SECTION;
3290b57cec5SDimitry Andric       break;
3300b57cec5SDimitry Andric     case 'y':
33106c3fb27SDimitry Andric       if (!(TT.isARM() || TT.isThumb()))
33206c3fb27SDimitry Andric         return -1U;
3330b57cec5SDimitry Andric       flags |= ELF::SHF_ARM_PURECODE;
3340b57cec5SDimitry Andric       break;
3350b57cec5SDimitry Andric     case 's':
33606c3fb27SDimitry Andric       if (TT.getArch() != Triple::hexagon)
33706c3fb27SDimitry Andric         return -1U;
3380b57cec5SDimitry Andric       flags |= ELF::SHF_HEX_GPREL;
3390b57cec5SDimitry Andric       break;
3400b57cec5SDimitry Andric     case 'G':
3410b57cec5SDimitry Andric       flags |= ELF::SHF_GROUP;
3420b57cec5SDimitry Andric       break;
34306c3fb27SDimitry Andric     case 'l':
34406c3fb27SDimitry Andric       if (TT.getArch() != Triple::x86_64)
34506c3fb27SDimitry Andric         return -1U;
34606c3fb27SDimitry Andric       flags |= ELF::SHF_X86_64_LARGE;
34706c3fb27SDimitry Andric       break;
348fe6060f1SDimitry Andric     case 'R':
34981ad6265SDimitry Andric       if (TT.isOSSolaris())
35081ad6265SDimitry Andric         flags |= ELF::SHF_SUNW_NODISCARD;
35181ad6265SDimitry Andric       else
352fe6060f1SDimitry Andric         flags |= ELF::SHF_GNU_RETAIN;
353fe6060f1SDimitry Andric       break;
3540b57cec5SDimitry Andric     case '?':
3550b57cec5SDimitry Andric       *UseLastGroup = true;
3560b57cec5SDimitry Andric       break;
3570b57cec5SDimitry Andric     default:
3580b57cec5SDimitry Andric       return -1U;
3590b57cec5SDimitry Andric     }
3600b57cec5SDimitry Andric   }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   return flags;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric unsigned ELFAsmParser::parseSunStyleSectionFlags() {
3660b57cec5SDimitry Andric   unsigned flags = 0;
3670b57cec5SDimitry Andric   while (getLexer().is(AsmToken::Hash)) {
3680b57cec5SDimitry Andric     Lex(); // Eat the #.
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::Identifier))
3710b57cec5SDimitry Andric       return -1U;
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric     StringRef flagId = getTok().getIdentifier();
3740b57cec5SDimitry Andric     if (flagId == "alloc")
3750b57cec5SDimitry Andric       flags |= ELF::SHF_ALLOC;
3760b57cec5SDimitry Andric     else if (flagId == "execinstr")
3770b57cec5SDimitry Andric       flags |= ELF::SHF_EXECINSTR;
3780b57cec5SDimitry Andric     else if (flagId == "write")
3790b57cec5SDimitry Andric       flags |= ELF::SHF_WRITE;
3800b57cec5SDimitry Andric     else if (flagId == "tls")
3810b57cec5SDimitry Andric       flags |= ELF::SHF_TLS;
3820b57cec5SDimitry Andric     else
3830b57cec5SDimitry Andric       return -1U;
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     Lex(); // Eat the flag.
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::Comma))
3880b57cec5SDimitry Andric         break;
3890b57cec5SDimitry Andric     Lex(); // Eat the comma.
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric   return flags;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
39681ad6265SDimitry Andric   getStreamer().pushSection();
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   if (ParseSectionArguments(/*IsPush=*/true, loc)) {
39981ad6265SDimitry Andric     getStreamer().popSection();
4000b57cec5SDimitry Andric     return true;
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   return false;
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
40781ad6265SDimitry Andric   if (!getStreamer().popSection())
4080b57cec5SDimitry Andric     return TokError(".popsection without corresponding .pushsection");
4090b57cec5SDimitry Andric   return false;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
4130b57cec5SDimitry Andric   return ParseSectionArguments(/*IsPush=*/false, loc);
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {
4170b57cec5SDimitry Andric   MCAsmLexer &L = getLexer();
4180b57cec5SDimitry Andric   if (L.isNot(AsmToken::Comma))
4190b57cec5SDimitry Andric     return false;
4200b57cec5SDimitry Andric   Lex();
4210b57cec5SDimitry Andric   if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) &&
4220b57cec5SDimitry Andric       L.isNot(AsmToken::String)) {
4230b57cec5SDimitry Andric     if (L.getAllowAtInIdentifier())
4240b57cec5SDimitry Andric       return TokError("expected '@<type>', '%<type>' or \"<type>\"");
4250b57cec5SDimitry Andric     else
4260b57cec5SDimitry Andric       return TokError("expected '%<type>' or \"<type>\"");
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric   if (!L.is(AsmToken::String))
4290b57cec5SDimitry Andric     Lex();
4300b57cec5SDimitry Andric   if (L.is(AsmToken::Integer)) {
4310b57cec5SDimitry Andric     TypeName = getTok().getString();
4320b57cec5SDimitry Andric     Lex();
4330b57cec5SDimitry Andric   } else if (getParser().parseIdentifier(TypeName))
434bdd1243dSDimitry Andric     return TokError("expected identifier");
4350b57cec5SDimitry Andric   return false;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric bool ELFAsmParser::parseMergeSize(int64_t &Size) {
4390b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
4400b57cec5SDimitry Andric     return TokError("expected the entry size");
4410b57cec5SDimitry Andric   Lex();
4420b57cec5SDimitry Andric   if (getParser().parseAbsoluteExpression(Size))
4430b57cec5SDimitry Andric     return true;
4440b57cec5SDimitry Andric   if (Size <= 0)
4450b57cec5SDimitry Andric     return TokError("entry size must be positive");
4460b57cec5SDimitry Andric   return false;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
449fe6060f1SDimitry Andric bool ELFAsmParser::parseGroup(StringRef &GroupName, bool &IsComdat) {
4500b57cec5SDimitry Andric   MCAsmLexer &L = getLexer();
4510b57cec5SDimitry Andric   if (L.isNot(AsmToken::Comma))
4520b57cec5SDimitry Andric     return TokError("expected group name");
4530b57cec5SDimitry Andric   Lex();
4540b57cec5SDimitry Andric   if (L.is(AsmToken::Integer)) {
4550b57cec5SDimitry Andric     GroupName = getTok().getString();
4560b57cec5SDimitry Andric     Lex();
4570b57cec5SDimitry Andric   } else if (getParser().parseIdentifier(GroupName)) {
4580b57cec5SDimitry Andric     return TokError("invalid group name");
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric   if (L.is(AsmToken::Comma)) {
4610b57cec5SDimitry Andric     Lex();
4620b57cec5SDimitry Andric     StringRef Linkage;
4630b57cec5SDimitry Andric     if (getParser().parseIdentifier(Linkage))
4640b57cec5SDimitry Andric       return TokError("invalid linkage");
4650b57cec5SDimitry Andric     if (Linkage != "comdat")
4660b57cec5SDimitry Andric       return TokError("Linkage must be 'comdat'");
467fe6060f1SDimitry Andric     IsComdat = true;
468fe6060f1SDimitry Andric   } else {
469fe6060f1SDimitry Andric     IsComdat = false;
4700b57cec5SDimitry Andric   }
4710b57cec5SDimitry Andric   return false;
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
4745ffd83dbSDimitry Andric bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) {
4750b57cec5SDimitry Andric   MCAsmLexer &L = getLexer();
4760b57cec5SDimitry Andric   if (L.isNot(AsmToken::Comma))
4775ffd83dbSDimitry Andric     return TokError("expected linked-to symbol");
4780b57cec5SDimitry Andric   Lex();
4790b57cec5SDimitry Andric   StringRef Name;
4805ffd83dbSDimitry Andric   SMLoc StartLoc = L.getLoc();
481e8d8bef9SDimitry Andric   if (getParser().parseIdentifier(Name)) {
482e8d8bef9SDimitry Andric     if (getParser().getTok().getString() == "0") {
483e8d8bef9SDimitry Andric       getParser().Lex();
484e8d8bef9SDimitry Andric       LinkedToSym = nullptr;
485e8d8bef9SDimitry Andric       return false;
486e8d8bef9SDimitry Andric     }
4875ffd83dbSDimitry Andric     return TokError("invalid linked-to symbol");
488e8d8bef9SDimitry Andric   }
4895ffd83dbSDimitry Andric   LinkedToSym = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));
4905ffd83dbSDimitry Andric   if (!LinkedToSym || !LinkedToSym->isInSection())
4915ffd83dbSDimitry Andric     return Error(StartLoc, "linked-to symbol is not in a section: " + Name);
4920b57cec5SDimitry Andric   return false;
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) {
4960b57cec5SDimitry Andric   MCAsmLexer &L = getLexer();
4970b57cec5SDimitry Andric   if (L.isNot(AsmToken::Comma))
4980b57cec5SDimitry Andric     return false;
4990b57cec5SDimitry Andric   Lex();
5000b57cec5SDimitry Andric   StringRef UniqueStr;
5010b57cec5SDimitry Andric   if (getParser().parseIdentifier(UniqueStr))
502bdd1243dSDimitry Andric     return TokError("expected identifier");
5030b57cec5SDimitry Andric   if (UniqueStr != "unique")
5040b57cec5SDimitry Andric     return TokError("expected 'unique'");
5050b57cec5SDimitry Andric   if (L.isNot(AsmToken::Comma))
5060b57cec5SDimitry Andric     return TokError("expected commma");
5070b57cec5SDimitry Andric   Lex();
5080b57cec5SDimitry Andric   if (getParser().parseAbsoluteExpression(UniqueID))
5090b57cec5SDimitry Andric     return true;
5100b57cec5SDimitry Andric   if (UniqueID < 0)
5110b57cec5SDimitry Andric     return TokError("unique id must be positive");
5120b57cec5SDimitry Andric   if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
5130b57cec5SDimitry Andric     return TokError("unique id is too large");
5140b57cec5SDimitry Andric   return false;
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
51804eeddc0SDimitry Andric   return SectionName.consume_front(Prefix) &&
51904eeddc0SDimitry Andric          (SectionName.empty() || SectionName[0] == '.');
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric 
522349cc55cSDimitry Andric static bool allowSectionTypeMismatch(const Triple &TT, StringRef SectionName,
523349cc55cSDimitry Andric                                      unsigned Type) {
524349cc55cSDimitry Andric   if (TT.getArch() == Triple::x86_64) {
525349cc55cSDimitry Andric     // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,
526349cc55cSDimitry Andric     // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't
527349cc55cSDimitry Andric     // error for SHT_PROGBITS .eh_frame
528349cc55cSDimitry Andric     return SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS;
529349cc55cSDimitry Andric   }
530349cc55cSDimitry Andric   if (TT.isMIPS()) {
531349cc55cSDimitry Andric     // MIPS .debug_* sections should have SHT_MIPS_DWARF section type to
532349cc55cSDimitry Andric     // distinguish among sections contain DWARF and ECOFF debug formats,
533349cc55cSDimitry Andric     // but in assembly files these sections have SHT_PROGBITS type.
5345f757f3fSDimitry Andric     return SectionName.starts_with(".debug_") && Type == ELF::SHT_PROGBITS;
535349cc55cSDimitry Andric   }
536349cc55cSDimitry Andric   return false;
537349cc55cSDimitry Andric }
538349cc55cSDimitry Andric 
5390b57cec5SDimitry Andric bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
5400b57cec5SDimitry Andric   StringRef SectionName;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   if (ParseSectionName(SectionName))
543bdd1243dSDimitry Andric     return TokError("expected identifier");
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   StringRef TypeName;
5460b57cec5SDimitry Andric   int64_t Size = 0;
5470b57cec5SDimitry Andric   StringRef GroupName;
548fe6060f1SDimitry Andric   bool IsComdat = false;
5490b57cec5SDimitry Andric   unsigned Flags = 0;
550fe6060f1SDimitry Andric   unsigned extraFlags = 0;
5510b57cec5SDimitry Andric   const MCExpr *Subsection = nullptr;
5520b57cec5SDimitry Andric   bool UseLastGroup = false;
5535ffd83dbSDimitry Andric   MCSymbolELF *LinkedToSym = nullptr;
5540b57cec5SDimitry Andric   int64_t UniqueID = ~0;
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   // Set the defaults first.
55704eeddc0SDimitry Andric   if (hasPrefix(SectionName, ".rodata") || SectionName == ".rodata1")
5580b57cec5SDimitry Andric     Flags |= ELF::SHF_ALLOC;
5590b57cec5SDimitry Andric   else if (SectionName == ".fini" || SectionName == ".init" ||
56004eeddc0SDimitry Andric            hasPrefix(SectionName, ".text"))
5610b57cec5SDimitry Andric     Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
56204eeddc0SDimitry Andric   else if (hasPrefix(SectionName, ".data") || SectionName == ".data1" ||
56304eeddc0SDimitry Andric            hasPrefix(SectionName, ".bss") ||
56404eeddc0SDimitry Andric            hasPrefix(SectionName, ".init_array") ||
56504eeddc0SDimitry Andric            hasPrefix(SectionName, ".fini_array") ||
56604eeddc0SDimitry Andric            hasPrefix(SectionName, ".preinit_array"))
5670b57cec5SDimitry Andric     Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
56804eeddc0SDimitry Andric   else if (hasPrefix(SectionName, ".tdata") || hasPrefix(SectionName, ".tbss"))
5690b57cec5SDimitry Andric     Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
5720b57cec5SDimitry Andric     Lex();
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric     if (IsPush && getLexer().isNot(AsmToken::String)) {
5750b57cec5SDimitry Andric       if (getParser().parseExpression(Subsection))
5760b57cec5SDimitry Andric         return true;
5770b57cec5SDimitry Andric       if (getLexer().isNot(AsmToken::Comma))
5780b57cec5SDimitry Andric         goto EndStmt;
5790b57cec5SDimitry Andric       Lex();
5800b57cec5SDimitry Andric     }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::String)) {
583a4a491e2SDimitry Andric       if (getLexer().isNot(AsmToken::Hash))
584bdd1243dSDimitry Andric         return TokError("expected string");
5850b57cec5SDimitry Andric       extraFlags = parseSunStyleSectionFlags();
5860b57cec5SDimitry Andric     } else {
5870b57cec5SDimitry Andric       StringRef FlagsStr = getTok().getStringContents();
5880b57cec5SDimitry Andric       Lex();
58981ad6265SDimitry Andric       extraFlags = parseSectionFlags(getContext().getTargetTriple(), FlagsStr,
59081ad6265SDimitry Andric                                      &UseLastGroup);
5910b57cec5SDimitry Andric     }
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric     if (extraFlags == -1U)
5940b57cec5SDimitry Andric       return TokError("unknown flag");
5950b57cec5SDimitry Andric     Flags |= extraFlags;
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric     bool Mergeable = Flags & ELF::SHF_MERGE;
5980b57cec5SDimitry Andric     bool Group = Flags & ELF::SHF_GROUP;
5990b57cec5SDimitry Andric     if (Group && UseLastGroup)
6000b57cec5SDimitry Andric       return TokError("Section cannot specifiy a group name while also acting "
6010b57cec5SDimitry Andric                       "as a member of the last group");
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric     if (maybeParseSectionType(TypeName))
6040b57cec5SDimitry Andric       return true;
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric     MCAsmLexer &L = getLexer();
6070b57cec5SDimitry Andric     if (TypeName.empty()) {
6080b57cec5SDimitry Andric       if (Mergeable)
6090b57cec5SDimitry Andric         return TokError("Mergeable section must specify the type");
6100b57cec5SDimitry Andric       if (Group)
6110b57cec5SDimitry Andric         return TokError("Group section must specify the type");
6120b57cec5SDimitry Andric       if (L.isNot(AsmToken::EndOfStatement))
613bdd1243dSDimitry Andric         return TokError("expected end of directive");
6140b57cec5SDimitry Andric     }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric     if (Mergeable)
6170b57cec5SDimitry Andric       if (parseMergeSize(Size))
6180b57cec5SDimitry Andric         return true;
6190b57cec5SDimitry Andric     if (Flags & ELF::SHF_LINK_ORDER)
6205ffd83dbSDimitry Andric       if (parseLinkedToSym(LinkedToSym))
6210b57cec5SDimitry Andric         return true;
622297eecfbSDimitry Andric     if (Group)
623297eecfbSDimitry Andric       if (parseGroup(GroupName, IsComdat))
624297eecfbSDimitry Andric         return true;
6250b57cec5SDimitry Andric     if (maybeParseUniqueID(UniqueID))
6260b57cec5SDimitry Andric       return true;
6270b57cec5SDimitry Andric   }
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric EndStmt:
6300b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
631bdd1243dSDimitry Andric     return TokError("expected end of directive");
6320b57cec5SDimitry Andric   Lex();
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   unsigned Type = ELF::SHT_PROGBITS;
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   if (TypeName.empty()) {
6375f757f3fSDimitry Andric     if (SectionName.starts_with(".note"))
6380b57cec5SDimitry Andric       Type = ELF::SHT_NOTE;
63904eeddc0SDimitry Andric     else if (hasPrefix(SectionName, ".init_array"))
6400b57cec5SDimitry Andric       Type = ELF::SHT_INIT_ARRAY;
64104eeddc0SDimitry Andric     else if (hasPrefix(SectionName, ".bss"))
6420b57cec5SDimitry Andric       Type = ELF::SHT_NOBITS;
64304eeddc0SDimitry Andric     else if (hasPrefix(SectionName, ".tbss"))
6440b57cec5SDimitry Andric       Type = ELF::SHT_NOBITS;
64504eeddc0SDimitry Andric     else if (hasPrefix(SectionName, ".fini_array"))
6460b57cec5SDimitry Andric       Type = ELF::SHT_FINI_ARRAY;
64704eeddc0SDimitry Andric     else if (hasPrefix(SectionName, ".preinit_array"))
6480b57cec5SDimitry Andric       Type = ELF::SHT_PREINIT_ARRAY;
6490b57cec5SDimitry Andric   } else {
6500b57cec5SDimitry Andric     if (TypeName == "init_array")
6510b57cec5SDimitry Andric       Type = ELF::SHT_INIT_ARRAY;
6520b57cec5SDimitry Andric     else if (TypeName == "fini_array")
6530b57cec5SDimitry Andric       Type = ELF::SHT_FINI_ARRAY;
6540b57cec5SDimitry Andric     else if (TypeName == "preinit_array")
6550b57cec5SDimitry Andric       Type = ELF::SHT_PREINIT_ARRAY;
6560b57cec5SDimitry Andric     else if (TypeName == "nobits")
6570b57cec5SDimitry Andric       Type = ELF::SHT_NOBITS;
6580b57cec5SDimitry Andric     else if (TypeName == "progbits")
6590b57cec5SDimitry Andric       Type = ELF::SHT_PROGBITS;
6600b57cec5SDimitry Andric     else if (TypeName == "note")
6610b57cec5SDimitry Andric       Type = ELF::SHT_NOTE;
6620b57cec5SDimitry Andric     else if (TypeName == "unwind")
6630b57cec5SDimitry Andric       Type = ELF::SHT_X86_64_UNWIND;
6640b57cec5SDimitry Andric     else if (TypeName == "llvm_odrtab")
6650b57cec5SDimitry Andric       Type = ELF::SHT_LLVM_ODRTAB;
6660b57cec5SDimitry Andric     else if (TypeName == "llvm_linker_options")
6670b57cec5SDimitry Andric       Type = ELF::SHT_LLVM_LINKER_OPTIONS;
6680b57cec5SDimitry Andric     else if (TypeName == "llvm_call_graph_profile")
6690b57cec5SDimitry Andric       Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
6700b57cec5SDimitry Andric     else if (TypeName == "llvm_dependent_libraries")
6710b57cec5SDimitry Andric       Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES;
6720b57cec5SDimitry Andric     else if (TypeName == "llvm_sympart")
6730b57cec5SDimitry Andric       Type = ELF::SHT_LLVM_SYMPART;
674e8d8bef9SDimitry Andric     else if (TypeName == "llvm_bb_addr_map")
675e8d8bef9SDimitry Andric       Type = ELF::SHT_LLVM_BB_ADDR_MAP;
676753f127fSDimitry Andric     else if (TypeName == "llvm_offloading")
677753f127fSDimitry Andric       Type = ELF::SHT_LLVM_OFFLOADING;
67806c3fb27SDimitry Andric     else if (TypeName == "llvm_lto")
67906c3fb27SDimitry Andric       Type = ELF::SHT_LLVM_LTO;
6800b57cec5SDimitry Andric     else if (TypeName.getAsInteger(0, Type))
6810b57cec5SDimitry Andric       return TokError("unknown section type");
6820b57cec5SDimitry Andric   }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   if (UseLastGroup) {
6850b57cec5SDimitry Andric     if (const MCSectionELF *Section =
686*0fca6ea1SDimitry Andric             cast_or_null<MCSectionELF>(getStreamer().getCurrentSectionOnly()))
6870b57cec5SDimitry Andric       if (const MCSymbol *Group = Section->getGroup()) {
6880b57cec5SDimitry Andric         GroupName = Group->getName();
689fe6060f1SDimitry Andric         IsComdat = Section->isComdat();
6900b57cec5SDimitry Andric         Flags |= ELF::SHF_GROUP;
6910b57cec5SDimitry Andric       }
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
694fe6060f1SDimitry Andric   MCSectionELF *Section =
695fe6060f1SDimitry Andric       getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,
696fe6060f1SDimitry Andric                                  IsComdat, UniqueID, LinkedToSym);
69781ad6265SDimitry Andric   getStreamer().switchSection(Section, Subsection);
6984824e7fdSDimitry Andric   // Check that flags are used consistently. However, the GNU assembler permits
6994824e7fdSDimitry Andric   // to leave out in subsequent uses of the same sections; for compatibility,
7004824e7fdSDimitry Andric   // do likewise.
7014824e7fdSDimitry Andric   if (!TypeName.empty() && Section->getType() != Type &&
702349cc55cSDimitry Andric       !allowSectionTypeMismatch(getContext().getTargetTriple(), SectionName,
703349cc55cSDimitry Andric                                 Type))
7045ffd83dbSDimitry Andric     Error(loc, "changed section type for " + SectionName + ", expected: 0x" +
7055ffd83dbSDimitry Andric                    utohexstr(Section->getType()));
706fe6060f1SDimitry Andric   if ((extraFlags || Size || !TypeName.empty()) && Section->getFlags() != Flags)
7075ffd83dbSDimitry Andric     Error(loc, "changed section flags for " + SectionName + ", expected: 0x" +
7085ffd83dbSDimitry Andric                    utohexstr(Section->getFlags()));
709fe6060f1SDimitry Andric   if ((extraFlags || Size || !TypeName.empty()) &&
710fe6060f1SDimitry Andric       Section->getEntrySize() != Size)
7115ffd83dbSDimitry Andric     Error(loc, "changed section entsize for " + SectionName +
7125ffd83dbSDimitry Andric                    ", expected: " + Twine(Section->getEntrySize()));
7130b57cec5SDimitry Andric 
714e8d8bef9SDimitry Andric   if (getContext().getGenDwarfForAssembly() &&
715e8d8bef9SDimitry Andric       (Section->getFlags() & ELF::SHF_ALLOC) &&
716e8d8bef9SDimitry Andric       (Section->getFlags() & ELF::SHF_EXECINSTR)) {
7175ffd83dbSDimitry Andric     bool InsertResult = getContext().addGenDwarfSection(Section);
718*0fca6ea1SDimitry Andric     if (InsertResult && getContext().getDwarfVersion() <= 2)
7190b57cec5SDimitry Andric       Warning(loc, "DWARF2 only supports one section per compilation unit");
7200b57cec5SDimitry Andric   }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   return false;
7230b57cec5SDimitry Andric }
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
7260b57cec5SDimitry Andric   MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
7270b57cec5SDimitry Andric   if (PreviousSection.first == nullptr)
7280b57cec5SDimitry Andric       return TokError(".previous without corresponding .section");
72981ad6265SDimitry Andric   getStreamer().switchSection(PreviousSection.first, PreviousSection.second);
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   return false;
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric static MCSymbolAttr MCAttrForString(StringRef Type) {
7350b57cec5SDimitry Andric   return StringSwitch<MCSymbolAttr>(Type)
7360b57cec5SDimitry Andric           .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
7370b57cec5SDimitry Andric           .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
7380b57cec5SDimitry Andric           .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
7390b57cec5SDimitry Andric           .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
7400b57cec5SDimitry Andric           .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
7410b57cec5SDimitry Andric           .Cases("STT_GNU_IFUNC", "gnu_indirect_function",
7420b57cec5SDimitry Andric                  MCSA_ELF_TypeIndFunction)
7430b57cec5SDimitry Andric           .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
7440b57cec5SDimitry Andric           .Default(MCSA_Invalid);
7450b57cec5SDimitry Andric }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric /// ParseDirectiveELFType
7480b57cec5SDimitry Andric ///  ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
7490b57cec5SDimitry Andric ///  ::= .type identifier , #attribute
7500b57cec5SDimitry Andric ///  ::= .type identifier , @attribute
7510b57cec5SDimitry Andric ///  ::= .type identifier , %attribute
7520b57cec5SDimitry Andric ///  ::= .type identifier , "attribute"
7530b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
7540b57cec5SDimitry Andric   StringRef Name;
7550b57cec5SDimitry Andric   if (getParser().parseIdentifier(Name))
756bdd1243dSDimitry Andric     return TokError("expected identifier");
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric   // Handle the identifier as the key symbol.
7590b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric   // NOTE the comma is optional in all cases.  It is only documented as being
7620b57cec5SDimitry Andric   // optional in the first case, however, GAS will silently treat the comma as
7630b57cec5SDimitry Andric   // optional in all cases.  Furthermore, although the documentation states that
7640b57cec5SDimitry Andric   // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
7650b57cec5SDimitry Andric   // accepts both the upper case name as well as the lower case aliases.
7660b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Comma))
7670b57cec5SDimitry Andric     Lex();
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Identifier) &&
7700b57cec5SDimitry Andric       getLexer().isNot(AsmToken::Hash) &&
7710b57cec5SDimitry Andric       getLexer().isNot(AsmToken::Percent) &&
7720b57cec5SDimitry Andric       getLexer().isNot(AsmToken::String)) {
7730b57cec5SDimitry Andric     if (!getLexer().getAllowAtInIdentifier())
7740b57cec5SDimitry Andric       return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
7750b57cec5SDimitry Andric                       "'%<type>' or \"<type>\"");
7760b57cec5SDimitry Andric     else if (getLexer().isNot(AsmToken::At))
7770b57cec5SDimitry Andric       return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
7780b57cec5SDimitry Andric                       "'%<type>' or \"<type>\"");
7790b57cec5SDimitry Andric   }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::String) &&
7820b57cec5SDimitry Andric       getLexer().isNot(AsmToken::Identifier))
7830b57cec5SDimitry Andric     Lex();
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   SMLoc TypeLoc = getLexer().getLoc();
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric   StringRef Type;
7880b57cec5SDimitry Andric   if (getParser().parseIdentifier(Type))
789bdd1243dSDimitry Andric     return TokError("expected symbol type");
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   MCSymbolAttr Attr = MCAttrForString(Type);
7920b57cec5SDimitry Andric   if (Attr == MCSA_Invalid)
793bdd1243dSDimitry Andric     return Error(TypeLoc, "unsupported attribute");
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
796bdd1243dSDimitry Andric     return TokError("expected end of directive");
7970b57cec5SDimitry Andric   Lex();
7980b57cec5SDimitry Andric 
7995ffd83dbSDimitry Andric   getStreamer().emitSymbolAttribute(Sym, Attr);
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric   return false;
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric /// ParseDirectiveIdent
8050b57cec5SDimitry Andric ///  ::= .ident string
8060b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
8070b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::String))
808bdd1243dSDimitry Andric     return TokError("expected string");
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric   StringRef Data = getTok().getIdentifier();
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric   Lex();
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
815bdd1243dSDimitry Andric     return TokError("expected end of directive");
8160b57cec5SDimitry Andric   Lex();
8170b57cec5SDimitry Andric 
8185ffd83dbSDimitry Andric   getStreamer().emitIdent(Data);
8190b57cec5SDimitry Andric   return false;
8200b57cec5SDimitry Andric }
8210b57cec5SDimitry Andric 
8220b57cec5SDimitry Andric /// ParseDirectiveSymver
8230b57cec5SDimitry Andric ///  ::= .symver foo, bar2@zed
8240b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
825fe6060f1SDimitry Andric   StringRef OriginalName, Name, Action;
826fe6060f1SDimitry Andric   if (getParser().parseIdentifier(OriginalName))
827bdd1243dSDimitry Andric     return TokError("expected identifier");
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
8300b57cec5SDimitry Andric     return TokError("expected a comma");
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   // ARM assembly uses @ for a comment...
8330b57cec5SDimitry Andric   // except when parsing the second parameter of the .symver directive.
8340b57cec5SDimitry Andric   // Force the next symbol to allow @ in the identifier, which is
8350b57cec5SDimitry Andric   // required for this directive and then reset it to its initial state.
8360b57cec5SDimitry Andric   const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
8370b57cec5SDimitry Andric   getLexer().setAllowAtInIdentifier(true);
8380b57cec5SDimitry Andric   Lex();
8390b57cec5SDimitry Andric   getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
8400b57cec5SDimitry Andric 
841fe6060f1SDimitry Andric   if (getParser().parseIdentifier(Name))
842bdd1243dSDimitry Andric     return TokError("expected identifier");
8430b57cec5SDimitry Andric 
844349cc55cSDimitry Andric   if (!Name.contains('@'))
8450b57cec5SDimitry Andric     return TokError("expected a '@' in the name");
846fe6060f1SDimitry Andric   bool KeepOriginalSym = !Name.contains("@@@");
847fe6060f1SDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
848fe6060f1SDimitry Andric     if (getParser().parseIdentifier(Action) || Action != "remove")
849fe6060f1SDimitry Andric       return TokError("expected 'remove'");
850fe6060f1SDimitry Andric     KeepOriginalSym = false;
851fe6060f1SDimitry Andric   }
852fe6060f1SDimitry Andric   (void)parseOptionalToken(AsmToken::EndOfStatement);
8530b57cec5SDimitry Andric 
854fe6060f1SDimitry Andric   getStreamer().emitELFSymverDirective(
855fe6060f1SDimitry Andric       getContext().getOrCreateSymbol(OriginalName), Name, KeepOriginalSym);
8560b57cec5SDimitry Andric   return false;
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric /// ParseDirectiveVersion
8600b57cec5SDimitry Andric ///  ::= .version string
8610b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
8620b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::String))
863bdd1243dSDimitry Andric     return TokError("expected string");
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric   StringRef Data = getTok().getIdentifier();
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric   Lex();
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
8700b57cec5SDimitry Andric 
87181ad6265SDimitry Andric   getStreamer().pushSection();
87281ad6265SDimitry Andric   getStreamer().switchSection(Note);
8735ffd83dbSDimitry Andric   getStreamer().emitInt32(Data.size() + 1); // namesz
8745ffd83dbSDimitry Andric   getStreamer().emitInt32(0);               // descsz = 0 (no description).
8755ffd83dbSDimitry Andric   getStreamer().emitInt32(1);               // type = NT_VERSION
8765ffd83dbSDimitry Andric   getStreamer().emitBytes(Data);            // name
8775ffd83dbSDimitry Andric   getStreamer().emitInt8(0);                // NUL
878bdd1243dSDimitry Andric   getStreamer().emitValueToAlignment(Align(4));
87981ad6265SDimitry Andric   getStreamer().popSection();
8800b57cec5SDimitry Andric   return false;
8810b57cec5SDimitry Andric }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric /// ParseDirectiveWeakref
8840b57cec5SDimitry Andric ///  ::= .weakref foo, bar
8850b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
8860b57cec5SDimitry Andric   // FIXME: Share code with the other alias building directives.
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric   StringRef AliasName;
8890b57cec5SDimitry Andric   if (getParser().parseIdentifier(AliasName))
890bdd1243dSDimitry Andric     return TokError("expected identifier");
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
8930b57cec5SDimitry Andric     return TokError("expected a comma");
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   Lex();
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   StringRef Name;
8980b57cec5SDimitry Andric   if (getParser().parseIdentifier(Name))
899bdd1243dSDimitry Andric     return TokError("expected identifier");
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
9040b57cec5SDimitry Andric 
9055ffd83dbSDimitry Andric   getStreamer().emitWeakReference(Alias, Sym);
9060b57cec5SDimitry Andric   return false;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
910*0fca6ea1SDimitry Andric   const MCExpr *Subsection = MCConstantExpr::create(0, getContext());
9110b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
9120b57cec5SDimitry Andric     if (getParser().parseExpression(Subsection))
9130b57cec5SDimitry Andric      return true;
9140b57cec5SDimitry Andric   }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
917bdd1243dSDimitry Andric     return TokError("expected end of directive");
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   Lex();
9200b57cec5SDimitry Andric 
921*0fca6ea1SDimitry Andric   return getStreamer().switchSection(getStreamer().getCurrentSectionOnly(),
922*0fca6ea1SDimitry Andric                                      Subsection);
9230b57cec5SDimitry Andric }
9240b57cec5SDimitry Andric 
9255ffd83dbSDimitry Andric bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
9265ffd83dbSDimitry Andric   return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
9270b57cec5SDimitry Andric }
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric namespace llvm {
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric MCAsmParserExtension *createELFAsmParser() {
9320b57cec5SDimitry Andric   return new ELFAsmParser;
9330b57cec5SDimitry Andric }
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric } // end namespace llvm
936