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