diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp')
-rw-r--r-- | contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp | 1752 |
1 files changed, 876 insertions, 876 deletions
diff --git a/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp index 65ac1d6b5b..243cdc2e3e 100644 --- a/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp +++ b/contrib/libs/llvm12/lib/MC/MCParser/ELFAsmParser.cpp @@ -1,888 +1,888 @@ -//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/MC/SectionKind.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/SMLoc.h" -#include <cassert> -#include <cstdint> -#include <utility> - -using namespace llvm; - -namespace { - -class ELFAsmParser : public MCAsmParserExtension { - template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)> - void addDirectiveHandler(StringRef Directive) { - MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( - this, HandleDirective<ELFAsmParser, HandlerMethod>); - - getParser().addDirectiveHandler(Directive, Handler); - } - - bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, - SectionKind Kind); - -public: - ELFAsmParser() { BracketExpressionsSupported = true; } - - void Initialize(MCAsmParser &Parser) override { - // Call the base implementation. - this->MCAsmParserExtension::Initialize(Parser); - - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); - addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); - addDirectiveHandler< - &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); - addDirectiveHandler< - &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); - addDirectiveHandler< - &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectivePushSection>(".pushsection"); - addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); - addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); - addDirectiveHandler< - &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection"); - addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile"); - } - - // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is - // the best way for us to get access to it? - bool ParseSectionDirectiveData(StringRef, SMLoc) { - return ParseSectionSwitch(".data", ELF::SHT_PROGBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC, - SectionKind::getData()); - } - bool ParseSectionDirectiveText(StringRef, SMLoc) { - return ParseSectionSwitch(".text", ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | - ELF::SHF_ALLOC, SectionKind::getText()); - } - bool ParseSectionDirectiveBSS(StringRef, SMLoc) { - return ParseSectionSwitch(".bss", ELF::SHT_NOBITS, - ELF::SHF_WRITE | - ELF::SHF_ALLOC, SectionKind::getBSS()); - } - bool ParseSectionDirectiveRoData(StringRef, SMLoc) { - return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC, - SectionKind::getReadOnly()); - } - bool ParseSectionDirectiveTData(StringRef, SMLoc) { - return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | - ELF::SHF_TLS | ELF::SHF_WRITE, - SectionKind::getThreadData()); - } - bool ParseSectionDirectiveTBSS(StringRef, SMLoc) { - return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS, - ELF::SHF_ALLOC | - ELF::SHF_TLS | ELF::SHF_WRITE, - SectionKind::getThreadBSS()); - } - bool ParseSectionDirectiveDataRel(StringRef, SMLoc) { - return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_WRITE, - SectionKind::getData()); - } - bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { - return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | - ELF::SHF_WRITE, - SectionKind::getReadOnlyWithRel()); - } - bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { - return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_WRITE, - SectionKind::getData()); - } - bool ParseDirectivePushSection(StringRef, SMLoc); - bool ParseDirectivePopSection(StringRef, SMLoc); - bool ParseDirectiveSection(StringRef, SMLoc); - bool ParseDirectiveSize(StringRef, SMLoc); - bool ParseDirectivePrevious(StringRef, SMLoc); - bool ParseDirectiveType(StringRef, SMLoc); - bool ParseDirectiveIdent(StringRef, SMLoc); - bool ParseDirectiveSymver(StringRef, SMLoc); - bool ParseDirectiveVersion(StringRef, SMLoc); - bool ParseDirectiveWeakref(StringRef, SMLoc); - bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); - bool ParseDirectiveSubsection(StringRef, SMLoc); - bool ParseDirectiveCGProfile(StringRef, SMLoc); - -private: - bool ParseSectionName(StringRef &SectionName); - bool ParseSectionArguments(bool IsPush, SMLoc loc); - unsigned parseSunStyleSectionFlags(); - bool maybeParseSectionType(StringRef &TypeName); - bool parseMergeSize(int64_t &Size); - bool parseGroup(StringRef &GroupName); - bool parseLinkedToSym(MCSymbolELF *&LinkedToSym); - bool maybeParseUniqueID(int64_t &UniqueID); -}; - -} // end anonymous namespace - -/// ParseDirectiveSymbolAttribute -/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] -bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { - MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) - .Case(".weak", MCSA_Weak) - .Case(".local", MCSA_Local) - .Case(".hidden", MCSA_Hidden) - .Case(".internal", MCSA_Internal) - .Case(".protected", MCSA_Protected) - .Default(MCSA_Invalid); - assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - while (true) { - StringRef Name; - - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - getStreamer().emitSymbolAttribute(Sym, Attr); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - } - } - - Lex(); - return false; -} - -bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind) { - const MCExpr *Subsection = nullptr; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getParser().parseExpression(Subsection)) - return true; - } - Lex(); - - getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags), - Subsection); - - return false; -} - -bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name)); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - const MCExpr *Expr; - if (getParser().parseExpression(Expr)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - Lex(); - - getStreamer().emitELFSize(Sym, Expr); - return false; -} - -bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { - // A section name can contain -, so we cannot just use - // parseIdentifier. - SMLoc FirstLoc = getLexer().getLoc(); - unsigned Size = 0; - - if (getLexer().is(AsmToken::String)) { - SectionName = getTok().getIdentifier(); - Lex(); - return false; - } - - while (!getParser().hasPendingError()) { - SMLoc PrevLoc = getLexer().getLoc(); - if (getLexer().is(AsmToken::Comma) || - getLexer().is(AsmToken::EndOfStatement)) - break; - - unsigned CurSize; - if (getLexer().is(AsmToken::String)) { - CurSize = getTok().getIdentifier().size() + 2; - Lex(); - } else if (getLexer().is(AsmToken::Identifier)) { - CurSize = getTok().getIdentifier().size(); - Lex(); - } else { - CurSize = getTok().getString().size(); - Lex(); - } - Size += CurSize; - SectionName = StringRef(FirstLoc.getPointer(), Size); - - // Make sure the following token is adjacent. - if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) - break; - } - if (Size == 0) - return true; - - return false; -} - -static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { - unsigned flags = 0; - - // If a valid numerical value is set for the section flag, use it verbatim - if (!flagsStr.getAsInteger(0, flags)) - return flags; - - for (char i : flagsStr) { - switch (i) { - case 'a': - flags |= ELF::SHF_ALLOC; - break; - case 'e': - flags |= ELF::SHF_EXCLUDE; - break; - case 'x': - flags |= ELF::SHF_EXECINSTR; - break; - case 'w': - flags |= ELF::SHF_WRITE; - break; - case 'o': - flags |= ELF::SHF_LINK_ORDER; - break; - case 'M': - flags |= ELF::SHF_MERGE; - break; - case 'S': - flags |= ELF::SHF_STRINGS; - break; - case 'T': - flags |= ELF::SHF_TLS; - break; - case 'c': - flags |= ELF::XCORE_SHF_CP_SECTION; - break; - case 'd': - flags |= ELF::XCORE_SHF_DP_SECTION; - break; - case 'y': - flags |= ELF::SHF_ARM_PURECODE; - break; - case 's': - flags |= ELF::SHF_HEX_GPREL; - break; - case 'G': - flags |= ELF::SHF_GROUP; - break; - case '?': - *UseLastGroup = true; - break; - default: - return -1U; - } - } - - return flags; -} - -unsigned ELFAsmParser::parseSunStyleSectionFlags() { - unsigned flags = 0; - while (getLexer().is(AsmToken::Hash)) { - Lex(); // Eat the #. - - if (!getLexer().is(AsmToken::Identifier)) - return -1U; - - StringRef flagId = getTok().getIdentifier(); - if (flagId == "alloc") - flags |= ELF::SHF_ALLOC; - else if (flagId == "execinstr") - flags |= ELF::SHF_EXECINSTR; - else if (flagId == "write") - flags |= ELF::SHF_WRITE; - else if (flagId == "tls") - flags |= ELF::SHF_TLS; - else - return -1U; - - Lex(); // Eat the flag. - - if (!getLexer().is(AsmToken::Comma)) - break; - Lex(); // Eat the comma. - } - return flags; -} - - -bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { - getStreamer().PushSection(); - - if (ParseSectionArguments(/*IsPush=*/true, loc)) { - getStreamer().PopSection(); - return true; - } - - return false; -} - -bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { - if (!getStreamer().PopSection()) - return TokError(".popsection without corresponding .pushsection"); - return false; -} - -bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { - return ParseSectionArguments(/*IsPush=*/false, loc); -} - -bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return false; - Lex(); - if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) && - L.isNot(AsmToken::String)) { - if (L.getAllowAtInIdentifier()) - return TokError("expected '@<type>', '%<type>' or \"<type>\""); - else - return TokError("expected '%<type>' or \"<type>\""); - } - if (!L.is(AsmToken::String)) - Lex(); - if (L.is(AsmToken::Integer)) { - TypeName = getTok().getString(); - Lex(); - } else if (getParser().parseIdentifier(TypeName)) - return TokError("expected identifier in directive"); - return false; -} - -bool ELFAsmParser::parseMergeSize(int64_t &Size) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected the entry size"); - Lex(); - if (getParser().parseAbsoluteExpression(Size)) - return true; - if (Size <= 0) - return TokError("entry size must be positive"); - return false; -} - -bool ELFAsmParser::parseGroup(StringRef &GroupName) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return TokError("expected group name"); - Lex(); - if (L.is(AsmToken::Integer)) { - GroupName = getTok().getString(); - Lex(); - } else if (getParser().parseIdentifier(GroupName)) { - return TokError("invalid group name"); - } - if (L.is(AsmToken::Comma)) { - Lex(); - StringRef Linkage; - if (getParser().parseIdentifier(Linkage)) - return TokError("invalid linkage"); - if (Linkage != "comdat") - return TokError("Linkage must be 'comdat'"); - } - return false; -} - -bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return TokError("expected linked-to symbol"); - Lex(); - StringRef Name; - SMLoc StartLoc = L.getLoc(); +//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SMLoc.h" +#include <cassert> +#include <cstdint> +#include <utility> + +using namespace llvm; + +namespace { + +class ELFAsmParser : public MCAsmParserExtension { + template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)> + void addDirectiveHandler(StringRef Directive) { + MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( + this, HandleDirective<ELFAsmParser, HandlerMethod>); + + getParser().addDirectiveHandler(Directive, Handler); + } + + bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind); + +public: + ELFAsmParser() { BracketExpressionsSupported = true; } + + void Initialize(MCAsmParser &Parser) override { + // Call the base implementation. + this->MCAsmParserExtension::Initialize(Parser); + + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); + addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); + addDirectiveHandler< + &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); + addDirectiveHandler< + &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); + addDirectiveHandler< + &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); + addDirectiveHandler< + &ELFAsmParser::ParseDirectivePushSection>(".pushsection"); + addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); + addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); + addDirectiveHandler< + &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected"); + addDirectiveHandler< + &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); + addDirectiveHandler< + &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile"); + } + + // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is + // the best way for us to get access to it? + bool ParseSectionDirectiveData(StringRef, SMLoc) { + return ParseSectionSwitch(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE | ELF::SHF_ALLOC, + SectionKind::getData()); + } + bool ParseSectionDirectiveText(StringRef, SMLoc) { + return ParseSectionSwitch(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, SectionKind::getText()); + } + bool ParseSectionDirectiveBSS(StringRef, SMLoc) { + return ParseSectionSwitch(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); + } + bool ParseSectionDirectiveRoData(StringRef, SMLoc) { + return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getReadOnly()); + } + bool ParseSectionDirectiveTData(StringRef, SMLoc) { + return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_TLS | ELF::SHF_WRITE, + SectionKind::getThreadData()); + } + bool ParseSectionDirectiveTBSS(StringRef, SMLoc) { + return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | + ELF::SHF_TLS | ELF::SHF_WRITE, + SectionKind::getThreadBSS()); + } + bool ParseSectionDirectiveDataRel(StringRef, SMLoc) { + return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE, + SectionKind::getData()); + } + bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { + return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + } + bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { + return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_WRITE, + SectionKind::getData()); + } + bool ParseDirectivePushSection(StringRef, SMLoc); + bool ParseDirectivePopSection(StringRef, SMLoc); + bool ParseDirectiveSection(StringRef, SMLoc); + bool ParseDirectiveSize(StringRef, SMLoc); + bool ParseDirectivePrevious(StringRef, SMLoc); + bool ParseDirectiveType(StringRef, SMLoc); + bool ParseDirectiveIdent(StringRef, SMLoc); + bool ParseDirectiveSymver(StringRef, SMLoc); + bool ParseDirectiveVersion(StringRef, SMLoc); + bool ParseDirectiveWeakref(StringRef, SMLoc); + bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); + bool ParseDirectiveSubsection(StringRef, SMLoc); + bool ParseDirectiveCGProfile(StringRef, SMLoc); + +private: + bool ParseSectionName(StringRef &SectionName); + bool ParseSectionArguments(bool IsPush, SMLoc loc); + unsigned parseSunStyleSectionFlags(); + bool maybeParseSectionType(StringRef &TypeName); + bool parseMergeSize(int64_t &Size); + bool parseGroup(StringRef &GroupName); + bool parseLinkedToSym(MCSymbolELF *&LinkedToSym); + bool maybeParseUniqueID(int64_t &UniqueID); +}; + +} // end anonymous namespace + +/// ParseDirectiveSymbolAttribute +/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] +bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { + MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) + .Case(".weak", MCSA_Weak) + .Case(".local", MCSA_Local) + .Case(".hidden", MCSA_Hidden) + .Case(".internal", MCSA_Internal) + .Case(".protected", MCSA_Protected) + .Default(MCSA_Invalid); + assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + while (true) { + StringRef Name; + + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + + getStreamer().emitSymbolAttribute(Sym, Attr); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind) { + const MCExpr *Subsection = nullptr; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getParser().parseExpression(Subsection)) + return true; + } + Lex(); + + getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags), + Subsection); + + return false; +} + +bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name)); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + const MCExpr *Expr; + if (getParser().parseExpression(Expr)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + Lex(); + + getStreamer().emitELFSize(Sym, Expr); + return false; +} + +bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { + // A section name can contain -, so we cannot just use + // parseIdentifier. + SMLoc FirstLoc = getLexer().getLoc(); + unsigned Size = 0; + + if (getLexer().is(AsmToken::String)) { + SectionName = getTok().getIdentifier(); + Lex(); + return false; + } + + while (!getParser().hasPendingError()) { + SMLoc PrevLoc = getLexer().getLoc(); + if (getLexer().is(AsmToken::Comma) || + getLexer().is(AsmToken::EndOfStatement)) + break; + + unsigned CurSize; + if (getLexer().is(AsmToken::String)) { + CurSize = getTok().getIdentifier().size() + 2; + Lex(); + } else if (getLexer().is(AsmToken::Identifier)) { + CurSize = getTok().getIdentifier().size(); + Lex(); + } else { + CurSize = getTok().getString().size(); + Lex(); + } + Size += CurSize; + SectionName = StringRef(FirstLoc.getPointer(), Size); + + // Make sure the following token is adjacent. + if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) + break; + } + if (Size == 0) + return true; + + return false; +} + +static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { + unsigned flags = 0; + + // If a valid numerical value is set for the section flag, use it verbatim + if (!flagsStr.getAsInteger(0, flags)) + return flags; + + for (char i : flagsStr) { + switch (i) { + case 'a': + flags |= ELF::SHF_ALLOC; + break; + case 'e': + flags |= ELF::SHF_EXCLUDE; + break; + case 'x': + flags |= ELF::SHF_EXECINSTR; + break; + case 'w': + flags |= ELF::SHF_WRITE; + break; + case 'o': + flags |= ELF::SHF_LINK_ORDER; + break; + case 'M': + flags |= ELF::SHF_MERGE; + break; + case 'S': + flags |= ELF::SHF_STRINGS; + break; + case 'T': + flags |= ELF::SHF_TLS; + break; + case 'c': + flags |= ELF::XCORE_SHF_CP_SECTION; + break; + case 'd': + flags |= ELF::XCORE_SHF_DP_SECTION; + break; + case 'y': + flags |= ELF::SHF_ARM_PURECODE; + break; + case 's': + flags |= ELF::SHF_HEX_GPREL; + break; + case 'G': + flags |= ELF::SHF_GROUP; + break; + case '?': + *UseLastGroup = true; + break; + default: + return -1U; + } + } + + return flags; +} + +unsigned ELFAsmParser::parseSunStyleSectionFlags() { + unsigned flags = 0; + while (getLexer().is(AsmToken::Hash)) { + Lex(); // Eat the #. + + if (!getLexer().is(AsmToken::Identifier)) + return -1U; + + StringRef flagId = getTok().getIdentifier(); + if (flagId == "alloc") + flags |= ELF::SHF_ALLOC; + else if (flagId == "execinstr") + flags |= ELF::SHF_EXECINSTR; + else if (flagId == "write") + flags |= ELF::SHF_WRITE; + else if (flagId == "tls") + flags |= ELF::SHF_TLS; + else + return -1U; + + Lex(); // Eat the flag. + + if (!getLexer().is(AsmToken::Comma)) + break; + Lex(); // Eat the comma. + } + return flags; +} + + +bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { + getStreamer().PushSection(); + + if (ParseSectionArguments(/*IsPush=*/true, loc)) { + getStreamer().PopSection(); + return true; + } + + return false; +} + +bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { + if (!getStreamer().PopSection()) + return TokError(".popsection without corresponding .pushsection"); + return false; +} + +bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { + return ParseSectionArguments(/*IsPush=*/false, loc); +} + +bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return false; + Lex(); + if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) && + L.isNot(AsmToken::String)) { + if (L.getAllowAtInIdentifier()) + return TokError("expected '@<type>', '%<type>' or \"<type>\""); + else + return TokError("expected '%<type>' or \"<type>\""); + } + if (!L.is(AsmToken::String)) + Lex(); + if (L.is(AsmToken::Integer)) { + TypeName = getTok().getString(); + Lex(); + } else if (getParser().parseIdentifier(TypeName)) + return TokError("expected identifier in directive"); + return false; +} + +bool ELFAsmParser::parseMergeSize(int64_t &Size) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected the entry size"); + Lex(); + if (getParser().parseAbsoluteExpression(Size)) + return true; + if (Size <= 0) + return TokError("entry size must be positive"); + return false; +} + +bool ELFAsmParser::parseGroup(StringRef &GroupName) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return TokError("expected group name"); + Lex(); + if (L.is(AsmToken::Integer)) { + GroupName = getTok().getString(); + Lex(); + } else if (getParser().parseIdentifier(GroupName)) { + return TokError("invalid group name"); + } + if (L.is(AsmToken::Comma)) { + Lex(); + StringRef Linkage; + if (getParser().parseIdentifier(Linkage)) + return TokError("invalid linkage"); + if (Linkage != "comdat") + return TokError("Linkage must be 'comdat'"); + } + return false; +} + +bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return TokError("expected linked-to symbol"); + Lex(); + StringRef Name; + SMLoc StartLoc = L.getLoc(); if (getParser().parseIdentifier(Name)) { if (getParser().getTok().getString() == "0") { getParser().Lex(); LinkedToSym = nullptr; return false; } - return TokError("invalid linked-to symbol"); + return TokError("invalid linked-to symbol"); } - LinkedToSym = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name)); - if (!LinkedToSym || !LinkedToSym->isInSection()) - return Error(StartLoc, "linked-to symbol is not in a section: " + Name); - return false; -} - -bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) { - MCAsmLexer &L = getLexer(); - if (L.isNot(AsmToken::Comma)) - return false; - Lex(); - StringRef UniqueStr; - if (getParser().parseIdentifier(UniqueStr)) - return TokError("expected identifier in directive"); - if (UniqueStr != "unique") - return TokError("expected 'unique'"); - if (L.isNot(AsmToken::Comma)) - return TokError("expected commma"); - Lex(); - if (getParser().parseAbsoluteExpression(UniqueID)) - return true; - if (UniqueID < 0) - return TokError("unique id must be positive"); - if (!isUInt<32>(UniqueID) || UniqueID == ~0U) - return TokError("unique id is too large"); - return false; -} - -static bool hasPrefix(StringRef SectionName, StringRef Prefix) { - return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back(); -} - -bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { - StringRef SectionName; - - if (ParseSectionName(SectionName)) - return TokError("expected identifier in directive"); - - StringRef TypeName; - int64_t Size = 0; - StringRef GroupName; - unsigned Flags = 0; - const MCExpr *Subsection = nullptr; - bool UseLastGroup = false; - MCSymbolELF *LinkedToSym = nullptr; - int64_t UniqueID = ~0; - - // Set the defaults first. - if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1") - Flags |= ELF::SHF_ALLOC; - else if (SectionName == ".fini" || SectionName == ".init" || - hasPrefix(SectionName, ".text.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; - else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" || - hasPrefix(SectionName, ".bss.") || - hasPrefix(SectionName, ".init_array.") || - hasPrefix(SectionName, ".fini_array.") || - hasPrefix(SectionName, ".preinit_array.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE; - else if (hasPrefix(SectionName, ".tdata.") || - hasPrefix(SectionName, ".tbss.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS; - - if (getLexer().is(AsmToken::Comma)) { - Lex(); - - if (IsPush && getLexer().isNot(AsmToken::String)) { - if (getParser().parseExpression(Subsection)) - return true; - if (getLexer().isNot(AsmToken::Comma)) - goto EndStmt; - Lex(); - } - - unsigned extraFlags; - - if (getLexer().isNot(AsmToken::String)) { - if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax() - || getLexer().isNot(AsmToken::Hash)) - return TokError("expected string in directive"); - extraFlags = parseSunStyleSectionFlags(); - } else { - StringRef FlagsStr = getTok().getStringContents(); - Lex(); - extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); - } - - if (extraFlags == -1U) - return TokError("unknown flag"); - Flags |= extraFlags; - - bool Mergeable = Flags & ELF::SHF_MERGE; - bool Group = Flags & ELF::SHF_GROUP; - if (Group && UseLastGroup) - return TokError("Section cannot specifiy a group name while also acting " - "as a member of the last group"); - - if (maybeParseSectionType(TypeName)) - return true; - - MCAsmLexer &L = getLexer(); - if (TypeName.empty()) { - if (Mergeable) - return TokError("Mergeable section must specify the type"); - if (Group) - return TokError("Group section must specify the type"); - if (L.isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - } - - if (Mergeable) - if (parseMergeSize(Size)) - return true; - if (Group) - if (parseGroup(GroupName)) - return true; - if (Flags & ELF::SHF_LINK_ORDER) - if (parseLinkedToSym(LinkedToSym)) - return true; - if (maybeParseUniqueID(UniqueID)) - return true; - } - -EndStmt: - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - Lex(); - - unsigned Type = ELF::SHT_PROGBITS; - - if (TypeName.empty()) { - if (SectionName.startswith(".note")) - Type = ELF::SHT_NOTE; - else if (hasPrefix(SectionName, ".init_array.")) - Type = ELF::SHT_INIT_ARRAY; - else if (hasPrefix(SectionName, ".bss.")) - Type = ELF::SHT_NOBITS; - else if (hasPrefix(SectionName, ".tbss.")) - Type = ELF::SHT_NOBITS; - else if (hasPrefix(SectionName, ".fini_array.")) - Type = ELF::SHT_FINI_ARRAY; - else if (hasPrefix(SectionName, ".preinit_array.")) - Type = ELF::SHT_PREINIT_ARRAY; - } else { - if (TypeName == "init_array") - Type = ELF::SHT_INIT_ARRAY; - else if (TypeName == "fini_array") - Type = ELF::SHT_FINI_ARRAY; - else if (TypeName == "preinit_array") - Type = ELF::SHT_PREINIT_ARRAY; - else if (TypeName == "nobits") - Type = ELF::SHT_NOBITS; - else if (TypeName == "progbits") - Type = ELF::SHT_PROGBITS; - else if (TypeName == "note") - Type = ELF::SHT_NOTE; - else if (TypeName == "unwind") - Type = ELF::SHT_X86_64_UNWIND; - else if (TypeName == "llvm_odrtab") - Type = ELF::SHT_LLVM_ODRTAB; - else if (TypeName == "llvm_linker_options") - Type = ELF::SHT_LLVM_LINKER_OPTIONS; - else if (TypeName == "llvm_call_graph_profile") - Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE; - else if (TypeName == "llvm_dependent_libraries") - Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES; - else if (TypeName == "llvm_sympart") - Type = ELF::SHT_LLVM_SYMPART; + LinkedToSym = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name)); + if (!LinkedToSym || !LinkedToSym->isInSection()) + return Error(StartLoc, "linked-to symbol is not in a section: " + Name); + return false; +} + +bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) { + MCAsmLexer &L = getLexer(); + if (L.isNot(AsmToken::Comma)) + return false; + Lex(); + StringRef UniqueStr; + if (getParser().parseIdentifier(UniqueStr)) + return TokError("expected identifier in directive"); + if (UniqueStr != "unique") + return TokError("expected 'unique'"); + if (L.isNot(AsmToken::Comma)) + return TokError("expected commma"); + Lex(); + if (getParser().parseAbsoluteExpression(UniqueID)) + return true; + if (UniqueID < 0) + return TokError("unique id must be positive"); + if (!isUInt<32>(UniqueID) || UniqueID == ~0U) + return TokError("unique id is too large"); + return false; +} + +static bool hasPrefix(StringRef SectionName, StringRef Prefix) { + return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back(); +} + +bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { + StringRef SectionName; + + if (ParseSectionName(SectionName)) + return TokError("expected identifier in directive"); + + StringRef TypeName; + int64_t Size = 0; + StringRef GroupName; + unsigned Flags = 0; + const MCExpr *Subsection = nullptr; + bool UseLastGroup = false; + MCSymbolELF *LinkedToSym = nullptr; + int64_t UniqueID = ~0; + + // Set the defaults first. + if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1") + Flags |= ELF::SHF_ALLOC; + else if (SectionName == ".fini" || SectionName == ".init" || + hasPrefix(SectionName, ".text.")) + Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; + else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" || + hasPrefix(SectionName, ".bss.") || + hasPrefix(SectionName, ".init_array.") || + hasPrefix(SectionName, ".fini_array.") || + hasPrefix(SectionName, ".preinit_array.")) + Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE; + else if (hasPrefix(SectionName, ".tdata.") || + hasPrefix(SectionName, ".tbss.")) + Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS; + + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + if (IsPush && getLexer().isNot(AsmToken::String)) { + if (getParser().parseExpression(Subsection)) + return true; + if (getLexer().isNot(AsmToken::Comma)) + goto EndStmt; + Lex(); + } + + unsigned extraFlags; + + if (getLexer().isNot(AsmToken::String)) { + if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax() + || getLexer().isNot(AsmToken::Hash)) + return TokError("expected string in directive"); + extraFlags = parseSunStyleSectionFlags(); + } else { + StringRef FlagsStr = getTok().getStringContents(); + Lex(); + extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); + } + + if (extraFlags == -1U) + return TokError("unknown flag"); + Flags |= extraFlags; + + bool Mergeable = Flags & ELF::SHF_MERGE; + bool Group = Flags & ELF::SHF_GROUP; + if (Group && UseLastGroup) + return TokError("Section cannot specifiy a group name while also acting " + "as a member of the last group"); + + if (maybeParseSectionType(TypeName)) + return true; + + MCAsmLexer &L = getLexer(); + if (TypeName.empty()) { + if (Mergeable) + return TokError("Mergeable section must specify the type"); + if (Group) + return TokError("Group section must specify the type"); + if (L.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + } + + if (Mergeable) + if (parseMergeSize(Size)) + return true; + if (Group) + if (parseGroup(GroupName)) + return true; + if (Flags & ELF::SHF_LINK_ORDER) + if (parseLinkedToSym(LinkedToSym)) + return true; + if (maybeParseUniqueID(UniqueID)) + return true; + } + +EndStmt: + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + Lex(); + + unsigned Type = ELF::SHT_PROGBITS; + + if (TypeName.empty()) { + if (SectionName.startswith(".note")) + Type = ELF::SHT_NOTE; + else if (hasPrefix(SectionName, ".init_array.")) + Type = ELF::SHT_INIT_ARRAY; + else if (hasPrefix(SectionName, ".bss.")) + Type = ELF::SHT_NOBITS; + else if (hasPrefix(SectionName, ".tbss.")) + Type = ELF::SHT_NOBITS; + else if (hasPrefix(SectionName, ".fini_array.")) + Type = ELF::SHT_FINI_ARRAY; + else if (hasPrefix(SectionName, ".preinit_array.")) + Type = ELF::SHT_PREINIT_ARRAY; + } else { + if (TypeName == "init_array") + Type = ELF::SHT_INIT_ARRAY; + else if (TypeName == "fini_array") + Type = ELF::SHT_FINI_ARRAY; + else if (TypeName == "preinit_array") + Type = ELF::SHT_PREINIT_ARRAY; + else if (TypeName == "nobits") + Type = ELF::SHT_NOBITS; + else if (TypeName == "progbits") + Type = ELF::SHT_PROGBITS; + else if (TypeName == "note") + Type = ELF::SHT_NOTE; + else if (TypeName == "unwind") + Type = ELF::SHT_X86_64_UNWIND; + else if (TypeName == "llvm_odrtab") + Type = ELF::SHT_LLVM_ODRTAB; + else if (TypeName == "llvm_linker_options") + Type = ELF::SHT_LLVM_LINKER_OPTIONS; + else if (TypeName == "llvm_call_graph_profile") + Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE; + else if (TypeName == "llvm_dependent_libraries") + Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES; + else if (TypeName == "llvm_sympart") + Type = ELF::SHT_LLVM_SYMPART; else if (TypeName == "llvm_bb_addr_map") Type = ELF::SHT_LLVM_BB_ADDR_MAP; - else if (TypeName.getAsInteger(0, Type)) - return TokError("unknown section type"); - } - - if (UseLastGroup) { - MCSectionSubPair CurrentSection = getStreamer().getCurrentSection(); - if (const MCSectionELF *Section = - cast_or_null<MCSectionELF>(CurrentSection.first)) - if (const MCSymbol *Group = Section->getGroup()) { - GroupName = Group->getName(); - Flags |= ELF::SHF_GROUP; - } - } - - MCSectionELF *Section = getContext().getELFSection( - SectionName, Type, Flags, Size, GroupName, UniqueID, LinkedToSym); - getStreamer().SwitchSection(Section, Subsection); - // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame, - // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't error - // for SHT_PROGBITS .eh_frame - if (Section->getType() != Type && - !(SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS)) - Error(loc, "changed section type for " + SectionName + ", expected: 0x" + - utohexstr(Section->getType())); - // Check that flags are used consistently. However, the GNU assembler permits - // to leave out in subsequent uses of the same sections; for compatibility, - // do likewise. - if ((Flags || Size || !TypeName.empty()) && Section->getFlags() != Flags) - Error(loc, "changed section flags for " + SectionName + ", expected: 0x" + - utohexstr(Section->getFlags())); - if ((Flags || Size || !TypeName.empty()) && Section->getEntrySize() != Size) - Error(loc, "changed section entsize for " + SectionName + - ", expected: " + Twine(Section->getEntrySize())); - + else if (TypeName.getAsInteger(0, Type)) + return TokError("unknown section type"); + } + + if (UseLastGroup) { + MCSectionSubPair CurrentSection = getStreamer().getCurrentSection(); + if (const MCSectionELF *Section = + cast_or_null<MCSectionELF>(CurrentSection.first)) + if (const MCSymbol *Group = Section->getGroup()) { + GroupName = Group->getName(); + Flags |= ELF::SHF_GROUP; + } + } + + MCSectionELF *Section = getContext().getELFSection( + SectionName, Type, Flags, Size, GroupName, UniqueID, LinkedToSym); + getStreamer().SwitchSection(Section, Subsection); + // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame, + // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't error + // for SHT_PROGBITS .eh_frame + if (Section->getType() != Type && + !(SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS)) + Error(loc, "changed section type for " + SectionName + ", expected: 0x" + + utohexstr(Section->getType())); + // Check that flags are used consistently. However, the GNU assembler permits + // to leave out in subsequent uses of the same sections; for compatibility, + // do likewise. + if ((Flags || Size || !TypeName.empty()) && Section->getFlags() != Flags) + Error(loc, "changed section flags for " + SectionName + ", expected: 0x" + + utohexstr(Section->getFlags())); + if ((Flags || Size || !TypeName.empty()) && Section->getEntrySize() != Size) + Error(loc, "changed section entsize for " + SectionName + + ", expected: " + Twine(Section->getEntrySize())); + if (getContext().getGenDwarfForAssembly() && (Section->getFlags() & ELF::SHF_ALLOC) && (Section->getFlags() & ELF::SHF_EXECINSTR)) { - bool InsertResult = getContext().addGenDwarfSection(Section); - if (InsertResult) { - if (getContext().getDwarfVersion() <= 2) - Warning(loc, "DWARF2 only supports one section per compilation unit"); - - if (!Section->getBeginSymbol()) { - MCSymbol *SectionStartSymbol = getContext().createTempSymbol(); - getStreamer().emitLabel(SectionStartSymbol); - Section->setBeginSymbol(SectionStartSymbol); - } - } - } - - return false; -} - -bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { - MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); - if (PreviousSection.first == nullptr) - return TokError(".previous without corresponding .section"); - getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); - - return false; -} - -static MCSymbolAttr MCAttrForString(StringRef Type) { - return StringSwitch<MCSymbolAttr>(Type) - .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction) - .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject) - .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS) - .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon) - .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType) - .Cases("STT_GNU_IFUNC", "gnu_indirect_function", - MCSA_ELF_TypeIndFunction) - .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) - .Default(MCSA_Invalid); -} - -/// ParseDirectiveELFType -/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> -/// ::= .type identifier , #attribute -/// ::= .type identifier , @attribute -/// ::= .type identifier , %attribute -/// ::= .type identifier , "attribute" -bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - // NOTE the comma is optional in all cases. It is only documented as being - // optional in the first case, however, GAS will silently treat the comma as - // optional in all cases. Furthermore, although the documentation states that - // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS - // accepts both the upper case name as well as the lower case aliases. - if (getLexer().is(AsmToken::Comma)) - Lex(); - - if (getLexer().isNot(AsmToken::Identifier) && - getLexer().isNot(AsmToken::Hash) && - getLexer().isNot(AsmToken::Percent) && - getLexer().isNot(AsmToken::String)) { - if (!getLexer().getAllowAtInIdentifier()) - return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', " - "'%<type>' or \"<type>\""); - else if (getLexer().isNot(AsmToken::At)) - return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " - "'%<type>' or \"<type>\""); - } - - if (getLexer().isNot(AsmToken::String) && - getLexer().isNot(AsmToken::Identifier)) - Lex(); - - SMLoc TypeLoc = getLexer().getLoc(); - - StringRef Type; - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - - MCSymbolAttr Attr = MCAttrForString(Type); - if (Attr == MCSA_Invalid) - return Error(TypeLoc, "unsupported attribute in '.type' directive"); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.type' directive"); - Lex(); - - getStreamer().emitSymbolAttribute(Sym, Attr); - - return false; -} - -/// ParseDirectiveIdent -/// ::= .ident string -bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { - if (getLexer().isNot(AsmToken::String)) - return TokError("unexpected token in '.ident' directive"); - - StringRef Data = getTok().getIdentifier(); - - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ident' directive"); - Lex(); - - getStreamer().emitIdent(Data); - return false; -} - -/// ParseDirectiveSymver -/// ::= .symver foo, bar2@zed -bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected a comma"); - - // ARM assembly uses @ for a comment... - // except when parsing the second parameter of the .symver directive. - // Force the next symbol to allow @ in the identifier, which is - // required for this directive and then reset it to its initial state. - const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier(); - getLexer().setAllowAtInIdentifier(true); - Lex(); - getLexer().setAllowAtInIdentifier(AllowAtInIdentifier); - - StringRef AliasName; - if (getParser().parseIdentifier(AliasName)) - return TokError("expected identifier in directive"); - - if (AliasName.find('@') == StringRef::npos) - return TokError("expected a '@' in the name"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - getStreamer().emitELFSymverDirective(AliasName, Sym); - return false; -} - -/// ParseDirectiveVersion -/// ::= .version string -bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) { - if (getLexer().isNot(AsmToken::String)) - return TokError("unexpected token in '.version' directive"); - - StringRef Data = getTok().getIdentifier(); - - Lex(); - - MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0); - - getStreamer().PushSection(); - getStreamer().SwitchSection(Note); - getStreamer().emitInt32(Data.size() + 1); // namesz - getStreamer().emitInt32(0); // descsz = 0 (no description). - getStreamer().emitInt32(1); // type = NT_VERSION - getStreamer().emitBytes(Data); // name - getStreamer().emitInt8(0); // NUL - getStreamer().emitValueToAlignment(4); - getStreamer().PopSection(); - return false; -} - -/// ParseDirectiveWeakref -/// ::= .weakref foo, bar -bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { - // FIXME: Share code with the other alias building directives. - - StringRef AliasName; - if (getParser().parseIdentifier(AliasName)) - return TokError("expected identifier in directive"); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("expected a comma"); - - Lex(); - - StringRef Name; - if (getParser().parseIdentifier(Name)) - return TokError("expected identifier in directive"); - - MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - - getStreamer().emitWeakReference(Alias, Sym); - return false; -} - -bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { - const MCExpr *Subsection = nullptr; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getParser().parseExpression(Subsection)) - return true; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in directive"); - - Lex(); - - getStreamer().SubSection(Subsection); - return false; -} - -bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) { - return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc); -} - -namespace llvm { - -MCAsmParserExtension *createELFAsmParser() { - return new ELFAsmParser; -} - -} // end namespace llvm + bool InsertResult = getContext().addGenDwarfSection(Section); + if (InsertResult) { + if (getContext().getDwarfVersion() <= 2) + Warning(loc, "DWARF2 only supports one section per compilation unit"); + + if (!Section->getBeginSymbol()) { + MCSymbol *SectionStartSymbol = getContext().createTempSymbol(); + getStreamer().emitLabel(SectionStartSymbol); + Section->setBeginSymbol(SectionStartSymbol); + } + } + } + + return false; +} + +bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { + MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); + if (PreviousSection.first == nullptr) + return TokError(".previous without corresponding .section"); + getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); + + return false; +} + +static MCSymbolAttr MCAttrForString(StringRef Type) { + return StringSwitch<MCSymbolAttr>(Type) + .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction) + .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject) + .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS) + .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon) + .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType) + .Cases("STT_GNU_IFUNC", "gnu_indirect_function", + MCSA_ELF_TypeIndFunction) + .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) + .Default(MCSA_Invalid); +} + +/// ParseDirectiveELFType +/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> +/// ::= .type identifier , #attribute +/// ::= .type identifier , @attribute +/// ::= .type identifier , %attribute +/// ::= .type identifier , "attribute" +bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + + // NOTE the comma is optional in all cases. It is only documented as being + // optional in the first case, however, GAS will silently treat the comma as + // optional in all cases. Furthermore, although the documentation states that + // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS + // accepts both the upper case name as well as the lower case aliases. + if (getLexer().is(AsmToken::Comma)) + Lex(); + + if (getLexer().isNot(AsmToken::Identifier) && + getLexer().isNot(AsmToken::Hash) && + getLexer().isNot(AsmToken::Percent) && + getLexer().isNot(AsmToken::String)) { + if (!getLexer().getAllowAtInIdentifier()) + return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', " + "'%<type>' or \"<type>\""); + else if (getLexer().isNot(AsmToken::At)) + return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " + "'%<type>' or \"<type>\""); + } + + if (getLexer().isNot(AsmToken::String) && + getLexer().isNot(AsmToken::Identifier)) + Lex(); + + SMLoc TypeLoc = getLexer().getLoc(); + + StringRef Type; + if (getParser().parseIdentifier(Type)) + return TokError("expected symbol type in directive"); + + MCSymbolAttr Attr = MCAttrForString(Type); + if (Attr == MCSA_Invalid) + return Error(TypeLoc, "unsupported attribute in '.type' directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.type' directive"); + Lex(); + + getStreamer().emitSymbolAttribute(Sym, Attr); + + return false; +} + +/// ParseDirectiveIdent +/// ::= .ident string +bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { + if (getLexer().isNot(AsmToken::String)) + return TokError("unexpected token in '.ident' directive"); + + StringRef Data = getTok().getIdentifier(); + + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.ident' directive"); + Lex(); + + getStreamer().emitIdent(Data); + return false; +} + +/// ParseDirectiveSymver +/// ::= .symver foo, bar2@zed +bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected a comma"); + + // ARM assembly uses @ for a comment... + // except when parsing the second parameter of the .symver directive. + // Force the next symbol to allow @ in the identifier, which is + // required for this directive and then reset it to its initial state. + const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier(); + getLexer().setAllowAtInIdentifier(true); + Lex(); + getLexer().setAllowAtInIdentifier(AllowAtInIdentifier); + + StringRef AliasName; + if (getParser().parseIdentifier(AliasName)) + return TokError("expected identifier in directive"); + + if (AliasName.find('@') == StringRef::npos) + return TokError("expected a '@' in the name"); + + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + getStreamer().emitELFSymverDirective(AliasName, Sym); + return false; +} + +/// ParseDirectiveVersion +/// ::= .version string +bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) { + if (getLexer().isNot(AsmToken::String)) + return TokError("unexpected token in '.version' directive"); + + StringRef Data = getTok().getIdentifier(); + + Lex(); + + MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0); + + getStreamer().PushSection(); + getStreamer().SwitchSection(Note); + getStreamer().emitInt32(Data.size() + 1); // namesz + getStreamer().emitInt32(0); // descsz = 0 (no description). + getStreamer().emitInt32(1); // type = NT_VERSION + getStreamer().emitBytes(Data); // name + getStreamer().emitInt8(0); // NUL + getStreamer().emitValueToAlignment(4); + getStreamer().PopSection(); + return false; +} + +/// ParseDirectiveWeakref +/// ::= .weakref foo, bar +bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { + // FIXME: Share code with the other alias building directives. + + StringRef AliasName; + if (getParser().parseIdentifier(AliasName)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected a comma"); + + Lex(); + + StringRef Name; + if (getParser().parseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); + + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + + getStreamer().emitWeakReference(Alias, Sym); + return false; +} + +bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { + const MCExpr *Subsection = nullptr; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getParser().parseExpression(Subsection)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + Lex(); + + getStreamer().SubSection(Subsection); + return false; +} + +bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) { + return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc); +} + +namespace llvm { + +MCAsmParserExtension *createELFAsmParser() { + return new ELFAsmParser; +} + +} // end namespace llvm |