Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCParser/ELFAsmParser.cpp
35266 views
//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ADT/StringExtras.h"9#include "llvm/ADT/StringRef.h"10#include "llvm/ADT/StringSwitch.h"11#include "llvm/BinaryFormat/ELF.h"12#include "llvm/MC/MCAsmInfo.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCDirectives.h"15#include "llvm/MC/MCParser/MCAsmLexer.h"16#include "llvm/MC/MCParser/MCAsmParser.h"17#include "llvm/MC/MCParser/MCAsmParserExtension.h"18#include "llvm/MC/MCSectionELF.h"19#include "llvm/MC/MCStreamer.h"20#include "llvm/MC/MCSymbol.h"21#include "llvm/MC/MCSymbolELF.h"22#include "llvm/MC/SectionKind.h"23#include "llvm/Support/Casting.h"24#include "llvm/Support/MathExtras.h"25#include "llvm/Support/SMLoc.h"26#include <cassert>27#include <cstdint>28#include <utility>2930using namespace llvm;3132namespace {3334class ELFAsmParser : public MCAsmParserExtension {35template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>36void addDirectiveHandler(StringRef Directive) {37MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(38this, HandleDirective<ELFAsmParser, HandlerMethod>);3940getParser().addDirectiveHandler(Directive, Handler);41}4243bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,44SectionKind Kind);4546public:47ELFAsmParser() { BracketExpressionsSupported = true; }4849void Initialize(MCAsmParser &Parser) override {50// Call the base implementation.51this->MCAsmParserExtension::Initialize(Parser);5253addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");54addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");55addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");56addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");57addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");58addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");59addDirectiveHandler<60&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");61addDirectiveHandler<62&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");63addDirectiveHandler<64&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");65addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");66addDirectiveHandler<67&ELFAsmParser::ParseDirectivePushSection>(".pushsection");68addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");69addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");70addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");71addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");72addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");73addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");74addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");75addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");76addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");77addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");78addDirectiveHandler<79&ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");80addDirectiveHandler<81&ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");82addDirectiveHandler<83&ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");84addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");85addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile");86}8788// FIXME: Part of this logic is duplicated in the MCELFStreamer. What is89// the best way for us to get access to it?90bool ParseSectionDirectiveData(StringRef, SMLoc) {91return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,92ELF::SHF_WRITE | ELF::SHF_ALLOC,93SectionKind::getData());94}95bool ParseSectionDirectiveText(StringRef, SMLoc) {96return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,97ELF::SHF_EXECINSTR |98ELF::SHF_ALLOC, SectionKind::getText());99}100bool ParseSectionDirectiveBSS(StringRef, SMLoc) {101return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,102ELF::SHF_WRITE |103ELF::SHF_ALLOC, SectionKind::getBSS());104}105bool ParseSectionDirectiveRoData(StringRef, SMLoc) {106return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,107ELF::SHF_ALLOC,108SectionKind::getReadOnly());109}110bool ParseSectionDirectiveTData(StringRef, SMLoc) {111return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,112ELF::SHF_ALLOC |113ELF::SHF_TLS | ELF::SHF_WRITE,114SectionKind::getThreadData());115}116bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {117return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,118ELF::SHF_ALLOC |119ELF::SHF_TLS | ELF::SHF_WRITE,120SectionKind::getThreadBSS());121}122bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {123return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,124ELF::SHF_ALLOC | ELF::SHF_WRITE,125SectionKind::getData());126}127bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {128return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,129ELF::SHF_ALLOC |130ELF::SHF_WRITE,131SectionKind::getReadOnlyWithRel());132}133bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {134return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,135ELF::SHF_ALLOC | ELF::SHF_WRITE,136SectionKind::getData());137}138bool ParseDirectivePushSection(StringRef, SMLoc);139bool ParseDirectivePopSection(StringRef, SMLoc);140bool ParseDirectiveSection(StringRef, SMLoc);141bool ParseDirectiveSize(StringRef, SMLoc);142bool ParseDirectivePrevious(StringRef, SMLoc);143bool ParseDirectiveType(StringRef, SMLoc);144bool ParseDirectiveIdent(StringRef, SMLoc);145bool ParseDirectiveSymver(StringRef, SMLoc);146bool ParseDirectiveVersion(StringRef, SMLoc);147bool ParseDirectiveWeakref(StringRef, SMLoc);148bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);149bool ParseDirectiveSubsection(StringRef, SMLoc);150bool ParseDirectiveCGProfile(StringRef, SMLoc);151152private:153bool ParseSectionName(StringRef &SectionName);154bool ParseSectionArguments(bool IsPush, SMLoc loc);155unsigned parseSunStyleSectionFlags();156bool maybeParseSectionType(StringRef &TypeName);157bool parseMergeSize(int64_t &Size);158bool parseGroup(StringRef &GroupName, bool &IsComdat);159bool parseLinkedToSym(MCSymbolELF *&LinkedToSym);160bool maybeParseUniqueID(int64_t &UniqueID);161};162163} // end anonymous namespace164165/// ParseDirectiveSymbolAttribute166/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]167bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {168MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)169.Case(".weak", MCSA_Weak)170.Case(".local", MCSA_Local)171.Case(".hidden", MCSA_Hidden)172.Case(".internal", MCSA_Internal)173.Case(".protected", MCSA_Protected)174.Default(MCSA_Invalid);175assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");176if (getLexer().isNot(AsmToken::EndOfStatement)) {177while (true) {178StringRef Name;179180if (getParser().parseIdentifier(Name))181return TokError("expected identifier");182183if (getParser().discardLTOSymbol(Name)) {184if (getLexer().is(AsmToken::EndOfStatement))185break;186continue;187}188189MCSymbol *Sym = getContext().getOrCreateSymbol(Name);190191getStreamer().emitSymbolAttribute(Sym, Attr);192193if (getLexer().is(AsmToken::EndOfStatement))194break;195196if (getLexer().isNot(AsmToken::Comma))197return TokError("expected comma");198Lex();199}200}201202Lex();203return false;204}205206bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,207unsigned Flags, SectionKind Kind) {208const MCExpr *Subsection = nullptr;209if (getLexer().isNot(AsmToken::EndOfStatement)) {210if (getParser().parseExpression(Subsection))211return true;212}213Lex();214215getStreamer().switchSection(getContext().getELFSection(Section, Type, Flags),216Subsection);217218return false;219}220221bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {222StringRef Name;223if (getParser().parseIdentifier(Name))224return TokError("expected identifier");225MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));226227if (getLexer().isNot(AsmToken::Comma))228return TokError("expected comma");229Lex();230231const MCExpr *Expr;232if (getParser().parseExpression(Expr))233return true;234235if (getLexer().isNot(AsmToken::EndOfStatement))236return TokError("unexpected token");237Lex();238239getStreamer().emitELFSize(Sym, Expr);240return false;241}242243bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {244// A section name can contain -, so we cannot just use245// parseIdentifier.246SMLoc FirstLoc = getLexer().getLoc();247unsigned Size = 0;248249if (getLexer().is(AsmToken::String)) {250SectionName = getTok().getIdentifier();251Lex();252return false;253}254255while (!getParser().hasPendingError()) {256SMLoc PrevLoc = getLexer().getLoc();257if (getLexer().is(AsmToken::Comma) ||258getLexer().is(AsmToken::EndOfStatement))259break;260261unsigned CurSize;262if (getLexer().is(AsmToken::String)) {263CurSize = getTok().getIdentifier().size() + 2;264Lex();265} else if (getLexer().is(AsmToken::Identifier)) {266CurSize = getTok().getIdentifier().size();267Lex();268} else {269CurSize = getTok().getString().size();270Lex();271}272Size += CurSize;273SectionName = StringRef(FirstLoc.getPointer(), Size);274275// Make sure the following token is adjacent.276if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())277break;278}279if (Size == 0)280return true;281282return false;283}284285static unsigned parseSectionFlags(const Triple &TT, StringRef flagsStr,286bool *UseLastGroup) {287unsigned flags = 0;288289// If a valid numerical value is set for the section flag, use it verbatim290if (!flagsStr.getAsInteger(0, flags))291return flags;292293for (char i : flagsStr) {294switch (i) {295case 'a':296flags |= ELF::SHF_ALLOC;297break;298case 'e':299flags |= ELF::SHF_EXCLUDE;300break;301case 'x':302flags |= ELF::SHF_EXECINSTR;303break;304case 'w':305flags |= ELF::SHF_WRITE;306break;307case 'o':308flags |= ELF::SHF_LINK_ORDER;309break;310case 'M':311flags |= ELF::SHF_MERGE;312break;313case 'S':314flags |= ELF::SHF_STRINGS;315break;316case 'T':317flags |= ELF::SHF_TLS;318break;319case 'c':320if (TT.getArch() != Triple::xcore)321return -1U;322flags |= ELF::XCORE_SHF_CP_SECTION;323break;324case 'd':325if (TT.getArch() != Triple::xcore)326return -1U;327flags |= ELF::XCORE_SHF_DP_SECTION;328break;329case 'y':330if (!(TT.isARM() || TT.isThumb()))331return -1U;332flags |= ELF::SHF_ARM_PURECODE;333break;334case 's':335if (TT.getArch() != Triple::hexagon)336return -1U;337flags |= ELF::SHF_HEX_GPREL;338break;339case 'G':340flags |= ELF::SHF_GROUP;341break;342case 'l':343if (TT.getArch() != Triple::x86_64)344return -1U;345flags |= ELF::SHF_X86_64_LARGE;346break;347case 'R':348if (TT.isOSSolaris())349flags |= ELF::SHF_SUNW_NODISCARD;350else351flags |= ELF::SHF_GNU_RETAIN;352break;353case '?':354*UseLastGroup = true;355break;356default:357return -1U;358}359}360361return flags;362}363364unsigned ELFAsmParser::parseSunStyleSectionFlags() {365unsigned flags = 0;366while (getLexer().is(AsmToken::Hash)) {367Lex(); // Eat the #.368369if (!getLexer().is(AsmToken::Identifier))370return -1U;371372StringRef flagId = getTok().getIdentifier();373if (flagId == "alloc")374flags |= ELF::SHF_ALLOC;375else if (flagId == "execinstr")376flags |= ELF::SHF_EXECINSTR;377else if (flagId == "write")378flags |= ELF::SHF_WRITE;379else if (flagId == "tls")380flags |= ELF::SHF_TLS;381else382return -1U;383384Lex(); // Eat the flag.385386if (!getLexer().is(AsmToken::Comma))387break;388Lex(); // Eat the comma.389}390return flags;391}392393394bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {395getStreamer().pushSection();396397if (ParseSectionArguments(/*IsPush=*/true, loc)) {398getStreamer().popSection();399return true;400}401402return false;403}404405bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {406if (!getStreamer().popSection())407return TokError(".popsection without corresponding .pushsection");408return false;409}410411bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {412return ParseSectionArguments(/*IsPush=*/false, loc);413}414415bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {416MCAsmLexer &L = getLexer();417if (L.isNot(AsmToken::Comma))418return false;419Lex();420if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) &&421L.isNot(AsmToken::String)) {422if (L.getAllowAtInIdentifier())423return TokError("expected '@<type>', '%<type>' or \"<type>\"");424else425return TokError("expected '%<type>' or \"<type>\"");426}427if (!L.is(AsmToken::String))428Lex();429if (L.is(AsmToken::Integer)) {430TypeName = getTok().getString();431Lex();432} else if (getParser().parseIdentifier(TypeName))433return TokError("expected identifier");434return false;435}436437bool ELFAsmParser::parseMergeSize(int64_t &Size) {438if (getLexer().isNot(AsmToken::Comma))439return TokError("expected the entry size");440Lex();441if (getParser().parseAbsoluteExpression(Size))442return true;443if (Size <= 0)444return TokError("entry size must be positive");445return false;446}447448bool ELFAsmParser::parseGroup(StringRef &GroupName, bool &IsComdat) {449MCAsmLexer &L = getLexer();450if (L.isNot(AsmToken::Comma))451return TokError("expected group name");452Lex();453if (L.is(AsmToken::Integer)) {454GroupName = getTok().getString();455Lex();456} else if (getParser().parseIdentifier(GroupName)) {457return TokError("invalid group name");458}459if (L.is(AsmToken::Comma)) {460Lex();461StringRef Linkage;462if (getParser().parseIdentifier(Linkage))463return TokError("invalid linkage");464if (Linkage != "comdat")465return TokError("Linkage must be 'comdat'");466IsComdat = true;467} else {468IsComdat = false;469}470return false;471}472473bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) {474MCAsmLexer &L = getLexer();475if (L.isNot(AsmToken::Comma))476return TokError("expected linked-to symbol");477Lex();478StringRef Name;479SMLoc StartLoc = L.getLoc();480if (getParser().parseIdentifier(Name)) {481if (getParser().getTok().getString() == "0") {482getParser().Lex();483LinkedToSym = nullptr;484return false;485}486return TokError("invalid linked-to symbol");487}488LinkedToSym = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));489if (!LinkedToSym || !LinkedToSym->isInSection())490return Error(StartLoc, "linked-to symbol is not in a section: " + Name);491return false;492}493494bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) {495MCAsmLexer &L = getLexer();496if (L.isNot(AsmToken::Comma))497return false;498Lex();499StringRef UniqueStr;500if (getParser().parseIdentifier(UniqueStr))501return TokError("expected identifier");502if (UniqueStr != "unique")503return TokError("expected 'unique'");504if (L.isNot(AsmToken::Comma))505return TokError("expected commma");506Lex();507if (getParser().parseAbsoluteExpression(UniqueID))508return true;509if (UniqueID < 0)510return TokError("unique id must be positive");511if (!isUInt<32>(UniqueID) || UniqueID == ~0U)512return TokError("unique id is too large");513return false;514}515516static bool hasPrefix(StringRef SectionName, StringRef Prefix) {517return SectionName.consume_front(Prefix) &&518(SectionName.empty() || SectionName[0] == '.');519}520521static bool allowSectionTypeMismatch(const Triple &TT, StringRef SectionName,522unsigned Type) {523if (TT.getArch() == Triple::x86_64) {524// x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,525// but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't526// error for SHT_PROGBITS .eh_frame527return SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS;528}529if (TT.isMIPS()) {530// MIPS .debug_* sections should have SHT_MIPS_DWARF section type to531// distinguish among sections contain DWARF and ECOFF debug formats,532// but in assembly files these sections have SHT_PROGBITS type.533return SectionName.starts_with(".debug_") && Type == ELF::SHT_PROGBITS;534}535return false;536}537538bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {539StringRef SectionName;540541if (ParseSectionName(SectionName))542return TokError("expected identifier");543544StringRef TypeName;545int64_t Size = 0;546StringRef GroupName;547bool IsComdat = false;548unsigned Flags = 0;549unsigned extraFlags = 0;550const MCExpr *Subsection = nullptr;551bool UseLastGroup = false;552MCSymbolELF *LinkedToSym = nullptr;553int64_t UniqueID = ~0;554555// Set the defaults first.556if (hasPrefix(SectionName, ".rodata") || SectionName == ".rodata1")557Flags |= ELF::SHF_ALLOC;558else if (SectionName == ".fini" || SectionName == ".init" ||559hasPrefix(SectionName, ".text"))560Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;561else if (hasPrefix(SectionName, ".data") || SectionName == ".data1" ||562hasPrefix(SectionName, ".bss") ||563hasPrefix(SectionName, ".init_array") ||564hasPrefix(SectionName, ".fini_array") ||565hasPrefix(SectionName, ".preinit_array"))566Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;567else if (hasPrefix(SectionName, ".tdata") || hasPrefix(SectionName, ".tbss"))568Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;569570if (getLexer().is(AsmToken::Comma)) {571Lex();572573if (IsPush && getLexer().isNot(AsmToken::String)) {574if (getParser().parseExpression(Subsection))575return true;576if (getLexer().isNot(AsmToken::Comma))577goto EndStmt;578Lex();579}580581if (getLexer().isNot(AsmToken::String)) {582if (getLexer().isNot(AsmToken::Hash))583return TokError("expected string");584extraFlags = parseSunStyleSectionFlags();585} else {586StringRef FlagsStr = getTok().getStringContents();587Lex();588extraFlags = parseSectionFlags(getContext().getTargetTriple(), FlagsStr,589&UseLastGroup);590}591592if (extraFlags == -1U)593return TokError("unknown flag");594Flags |= extraFlags;595596bool Mergeable = Flags & ELF::SHF_MERGE;597bool Group = Flags & ELF::SHF_GROUP;598if (Group && UseLastGroup)599return TokError("Section cannot specifiy a group name while also acting "600"as a member of the last group");601602if (maybeParseSectionType(TypeName))603return true;604605MCAsmLexer &L = getLexer();606if (TypeName.empty()) {607if (Mergeable)608return TokError("Mergeable section must specify the type");609if (Group)610return TokError("Group section must specify the type");611if (L.isNot(AsmToken::EndOfStatement))612return TokError("expected end of directive");613}614615if (Mergeable)616if (parseMergeSize(Size))617return true;618if (Flags & ELF::SHF_LINK_ORDER)619if (parseLinkedToSym(LinkedToSym))620return true;621if (Group)622if (parseGroup(GroupName, IsComdat))623return true;624if (maybeParseUniqueID(UniqueID))625return true;626}627628EndStmt:629if (getLexer().isNot(AsmToken::EndOfStatement))630return TokError("expected end of directive");631Lex();632633unsigned Type = ELF::SHT_PROGBITS;634635if (TypeName.empty()) {636if (SectionName.starts_with(".note"))637Type = ELF::SHT_NOTE;638else if (hasPrefix(SectionName, ".init_array"))639Type = ELF::SHT_INIT_ARRAY;640else if (hasPrefix(SectionName, ".bss"))641Type = ELF::SHT_NOBITS;642else if (hasPrefix(SectionName, ".tbss"))643Type = ELF::SHT_NOBITS;644else if (hasPrefix(SectionName, ".fini_array"))645Type = ELF::SHT_FINI_ARRAY;646else if (hasPrefix(SectionName, ".preinit_array"))647Type = ELF::SHT_PREINIT_ARRAY;648} else {649if (TypeName == "init_array")650Type = ELF::SHT_INIT_ARRAY;651else if (TypeName == "fini_array")652Type = ELF::SHT_FINI_ARRAY;653else if (TypeName == "preinit_array")654Type = ELF::SHT_PREINIT_ARRAY;655else if (TypeName == "nobits")656Type = ELF::SHT_NOBITS;657else if (TypeName == "progbits")658Type = ELF::SHT_PROGBITS;659else if (TypeName == "note")660Type = ELF::SHT_NOTE;661else if (TypeName == "unwind")662Type = ELF::SHT_X86_64_UNWIND;663else if (TypeName == "llvm_odrtab")664Type = ELF::SHT_LLVM_ODRTAB;665else if (TypeName == "llvm_linker_options")666Type = ELF::SHT_LLVM_LINKER_OPTIONS;667else if (TypeName == "llvm_call_graph_profile")668Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;669else if (TypeName == "llvm_dependent_libraries")670Type = ELF::SHT_LLVM_DEPENDENT_LIBRARIES;671else if (TypeName == "llvm_sympart")672Type = ELF::SHT_LLVM_SYMPART;673else if (TypeName == "llvm_bb_addr_map")674Type = ELF::SHT_LLVM_BB_ADDR_MAP;675else if (TypeName == "llvm_offloading")676Type = ELF::SHT_LLVM_OFFLOADING;677else if (TypeName == "llvm_lto")678Type = ELF::SHT_LLVM_LTO;679else if (TypeName.getAsInteger(0, Type))680return TokError("unknown section type");681}682683if (UseLastGroup) {684if (const MCSectionELF *Section =685cast_or_null<MCSectionELF>(getStreamer().getCurrentSectionOnly()))686if (const MCSymbol *Group = Section->getGroup()) {687GroupName = Group->getName();688IsComdat = Section->isComdat();689Flags |= ELF::SHF_GROUP;690}691}692693MCSectionELF *Section =694getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,695IsComdat, UniqueID, LinkedToSym);696getStreamer().switchSection(Section, Subsection);697// Check that flags are used consistently. However, the GNU assembler permits698// to leave out in subsequent uses of the same sections; for compatibility,699// do likewise.700if (!TypeName.empty() && Section->getType() != Type &&701!allowSectionTypeMismatch(getContext().getTargetTriple(), SectionName,702Type))703Error(loc, "changed section type for " + SectionName + ", expected: 0x" +704utohexstr(Section->getType()));705if ((extraFlags || Size || !TypeName.empty()) && Section->getFlags() != Flags)706Error(loc, "changed section flags for " + SectionName + ", expected: 0x" +707utohexstr(Section->getFlags()));708if ((extraFlags || Size || !TypeName.empty()) &&709Section->getEntrySize() != Size)710Error(loc, "changed section entsize for " + SectionName +711", expected: " + Twine(Section->getEntrySize()));712713if (getContext().getGenDwarfForAssembly() &&714(Section->getFlags() & ELF::SHF_ALLOC) &&715(Section->getFlags() & ELF::SHF_EXECINSTR)) {716bool InsertResult = getContext().addGenDwarfSection(Section);717if (InsertResult && getContext().getDwarfVersion() <= 2)718Warning(loc, "DWARF2 only supports one section per compilation unit");719}720721return false;722}723724bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {725MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();726if (PreviousSection.first == nullptr)727return TokError(".previous without corresponding .section");728getStreamer().switchSection(PreviousSection.first, PreviousSection.second);729730return false;731}732733static MCSymbolAttr MCAttrForString(StringRef Type) {734return StringSwitch<MCSymbolAttr>(Type)735.Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)736.Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)737.Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)738.Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)739.Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)740.Cases("STT_GNU_IFUNC", "gnu_indirect_function",741MCSA_ELF_TypeIndFunction)742.Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)743.Default(MCSA_Invalid);744}745746/// ParseDirectiveELFType747/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>748/// ::= .type identifier , #attribute749/// ::= .type identifier , @attribute750/// ::= .type identifier , %attribute751/// ::= .type identifier , "attribute"752bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {753StringRef Name;754if (getParser().parseIdentifier(Name))755return TokError("expected identifier");756757// Handle the identifier as the key symbol.758MCSymbol *Sym = getContext().getOrCreateSymbol(Name);759760// NOTE the comma is optional in all cases. It is only documented as being761// optional in the first case, however, GAS will silently treat the comma as762// optional in all cases. Furthermore, although the documentation states that763// the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS764// accepts both the upper case name as well as the lower case aliases.765if (getLexer().is(AsmToken::Comma))766Lex();767768if (getLexer().isNot(AsmToken::Identifier) &&769getLexer().isNot(AsmToken::Hash) &&770getLexer().isNot(AsmToken::Percent) &&771getLexer().isNot(AsmToken::String)) {772if (!getLexer().getAllowAtInIdentifier())773return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "774"'%<type>' or \"<type>\"");775else if (getLexer().isNot(AsmToken::At))776return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "777"'%<type>' or \"<type>\"");778}779780if (getLexer().isNot(AsmToken::String) &&781getLexer().isNot(AsmToken::Identifier))782Lex();783784SMLoc TypeLoc = getLexer().getLoc();785786StringRef Type;787if (getParser().parseIdentifier(Type))788return TokError("expected symbol type");789790MCSymbolAttr Attr = MCAttrForString(Type);791if (Attr == MCSA_Invalid)792return Error(TypeLoc, "unsupported attribute");793794if (getLexer().isNot(AsmToken::EndOfStatement))795return TokError("expected end of directive");796Lex();797798getStreamer().emitSymbolAttribute(Sym, Attr);799800return false;801}802803/// ParseDirectiveIdent804/// ::= .ident string805bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {806if (getLexer().isNot(AsmToken::String))807return TokError("expected string");808809StringRef Data = getTok().getIdentifier();810811Lex();812813if (getLexer().isNot(AsmToken::EndOfStatement))814return TokError("expected end of directive");815Lex();816817getStreamer().emitIdent(Data);818return false;819}820821/// ParseDirectiveSymver822/// ::= .symver foo, bar2@zed823bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {824StringRef OriginalName, Name, Action;825if (getParser().parseIdentifier(OriginalName))826return TokError("expected identifier");827828if (getLexer().isNot(AsmToken::Comma))829return TokError("expected a comma");830831// ARM assembly uses @ for a comment...832// except when parsing the second parameter of the .symver directive.833// Force the next symbol to allow @ in the identifier, which is834// required for this directive and then reset it to its initial state.835const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();836getLexer().setAllowAtInIdentifier(true);837Lex();838getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);839840if (getParser().parseIdentifier(Name))841return TokError("expected identifier");842843if (!Name.contains('@'))844return TokError("expected a '@' in the name");845bool KeepOriginalSym = !Name.contains("@@@");846if (parseOptionalToken(AsmToken::Comma)) {847if (getParser().parseIdentifier(Action) || Action != "remove")848return TokError("expected 'remove'");849KeepOriginalSym = false;850}851(void)parseOptionalToken(AsmToken::EndOfStatement);852853getStreamer().emitELFSymverDirective(854getContext().getOrCreateSymbol(OriginalName), Name, KeepOriginalSym);855return false;856}857858/// ParseDirectiveVersion859/// ::= .version string860bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {861if (getLexer().isNot(AsmToken::String))862return TokError("expected string");863864StringRef Data = getTok().getIdentifier();865866Lex();867868MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);869870getStreamer().pushSection();871getStreamer().switchSection(Note);872getStreamer().emitInt32(Data.size() + 1); // namesz873getStreamer().emitInt32(0); // descsz = 0 (no description).874getStreamer().emitInt32(1); // type = NT_VERSION875getStreamer().emitBytes(Data); // name876getStreamer().emitInt8(0); // NUL877getStreamer().emitValueToAlignment(Align(4));878getStreamer().popSection();879return false;880}881882/// ParseDirectiveWeakref883/// ::= .weakref foo, bar884bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {885// FIXME: Share code with the other alias building directives.886887StringRef AliasName;888if (getParser().parseIdentifier(AliasName))889return TokError("expected identifier");890891if (getLexer().isNot(AsmToken::Comma))892return TokError("expected a comma");893894Lex();895896StringRef Name;897if (getParser().parseIdentifier(Name))898return TokError("expected identifier");899900MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);901902MCSymbol *Sym = getContext().getOrCreateSymbol(Name);903904getStreamer().emitWeakReference(Alias, Sym);905return false;906}907908bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {909const MCExpr *Subsection = MCConstantExpr::create(0, getContext());910if (getLexer().isNot(AsmToken::EndOfStatement)) {911if (getParser().parseExpression(Subsection))912return true;913}914915if (getLexer().isNot(AsmToken::EndOfStatement))916return TokError("expected end of directive");917918Lex();919920return getStreamer().switchSection(getStreamer().getCurrentSectionOnly(),921Subsection);922}923924bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {925return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);926}927928namespace llvm {929930MCAsmParserExtension *createELFAsmParser() {931return new ELFAsmParser;932}933934} // end namespace llvm935936937