brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.9 KiB · 6c51d6b Raw
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