1 //===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 11 #include "llvm/ADT/StringSwitch.h" 12 #include "llvm/ADT/Twine.h" 13 #include "llvm/MC/MCAsmInfo.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCParser/MCAsmLexer.h" 17 #include "llvm/MC/MCSectionELF.h" 18 #include "llvm/MC/MCStreamer.h" 19 #include "llvm/MC/MCSymbolELF.h" 20 #include "llvm/Support/ELF.h" 21 using namespace llvm; 22 23 namespace { 24 25 class ELFAsmParser : public MCAsmParserExtension { 26 template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)> 27 void addDirectiveHandler(StringRef Directive) { 28 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 29 this, HandleDirective<ELFAsmParser, HandlerMethod>); 30 31 getParser().addDirectiveHandler(Directive, Handler); 32 } 33 34 bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, 35 SectionKind Kind); 36 37 public: 38 ELFAsmParser() { BracketExpressionsSupported = true; } 39 40 void Initialize(MCAsmParser &Parser) override { 41 // Call the base implementation. 42 this->MCAsmParserExtension::Initialize(Parser); 43 44 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); 45 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); 46 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); 47 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); 48 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); 49 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); 50 addDirectiveHandler< 51 &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); 52 addDirectiveHandler< 53 &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); 54 addDirectiveHandler< 55 &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); 56 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); 57 addDirectiveHandler< 58 &ELFAsmParser::ParseDirectivePushSection>(".pushsection"); 59 addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); 60 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); 61 addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); 62 addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); 63 addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); 64 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); 65 addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version"); 66 addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); 67 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); 68 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); 69 addDirectiveHandler< 70 &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected"); 71 addDirectiveHandler< 72 &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); 73 addDirectiveHandler< 74 &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); 75 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection"); 76 } 77 78 // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is 79 // the best way for us to get access to it? 80 bool ParseSectionDirectiveData(StringRef, SMLoc) { 81 return ParseSectionSwitch(".data", ELF::SHT_PROGBITS, 82 ELF::SHF_WRITE | ELF::SHF_ALLOC, 83 SectionKind::getData()); 84 } 85 bool ParseSectionDirectiveText(StringRef, SMLoc) { 86 return ParseSectionSwitch(".text", ELF::SHT_PROGBITS, 87 ELF::SHF_EXECINSTR | 88 ELF::SHF_ALLOC, SectionKind::getText()); 89 } 90 bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 91 return ParseSectionSwitch(".bss", ELF::SHT_NOBITS, 92 ELF::SHF_WRITE | 93 ELF::SHF_ALLOC, SectionKind::getBSS()); 94 } 95 bool ParseSectionDirectiveRoData(StringRef, SMLoc) { 96 return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS, 97 ELF::SHF_ALLOC, 98 SectionKind::getReadOnly()); 99 } 100 bool ParseSectionDirectiveTData(StringRef, SMLoc) { 101 return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS, 102 ELF::SHF_ALLOC | 103 ELF::SHF_TLS | ELF::SHF_WRITE, 104 SectionKind::getThreadData()); 105 } 106 bool ParseSectionDirectiveTBSS(StringRef, SMLoc) { 107 return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS, 108 ELF::SHF_ALLOC | 109 ELF::SHF_TLS | ELF::SHF_WRITE, 110 SectionKind::getThreadBSS()); 111 } 112 bool ParseSectionDirectiveDataRel(StringRef, SMLoc) { 113 return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS, 114 ELF::SHF_ALLOC | ELF::SHF_WRITE, 115 SectionKind::getData()); 116 } 117 bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { 118 return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS, 119 ELF::SHF_ALLOC | 120 ELF::SHF_WRITE, 121 SectionKind::getReadOnlyWithRel()); 122 } 123 bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { 124 return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS, 125 ELF::SHF_ALLOC | ELF::SHF_WRITE, 126 SectionKind::getData()); 127 } 128 bool ParseDirectivePushSection(StringRef, SMLoc); 129 bool ParseDirectivePopSection(StringRef, SMLoc); 130 bool ParseDirectiveSection(StringRef, SMLoc); 131 bool ParseDirectiveSize(StringRef, SMLoc); 132 bool ParseDirectivePrevious(StringRef, SMLoc); 133 bool ParseDirectiveType(StringRef, SMLoc); 134 bool ParseDirectiveIdent(StringRef, SMLoc); 135 bool ParseDirectiveSymver(StringRef, SMLoc); 136 bool ParseDirectiveVersion(StringRef, SMLoc); 137 bool ParseDirectiveWeakref(StringRef, SMLoc); 138 bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); 139 bool ParseDirectiveSubsection(StringRef, SMLoc); 140 141 private: 142 bool ParseSectionName(StringRef &SectionName); 143 bool ParseSectionArguments(bool IsPush, SMLoc loc); 144 unsigned parseSunStyleSectionFlags(); 145 }; 146 147 } 148 149 /// ParseDirectiveSymbolAttribute 150 /// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] 151 bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { 152 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) 153 .Case(".weak", MCSA_Weak) 154 .Case(".local", MCSA_Local) 155 .Case(".hidden", MCSA_Hidden) 156 .Case(".internal", MCSA_Internal) 157 .Case(".protected", MCSA_Protected) 158 .Default(MCSA_Invalid); 159 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); 160 if (getLexer().isNot(AsmToken::EndOfStatement)) { 161 for (;;) { 162 StringRef Name; 163 164 if (getParser().parseIdentifier(Name)) 165 return TokError("expected identifier in directive"); 166 167 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 168 169 getStreamer().EmitSymbolAttribute(Sym, Attr); 170 171 if (getLexer().is(AsmToken::EndOfStatement)) 172 break; 173 174 if (getLexer().isNot(AsmToken::Comma)) 175 return TokError("unexpected token in directive"); 176 Lex(); 177 } 178 } 179 180 Lex(); 181 return false; 182 } 183 184 bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, 185 unsigned Flags, SectionKind Kind) { 186 const MCExpr *Subsection = nullptr; 187 if (getLexer().isNot(AsmToken::EndOfStatement)) { 188 if (getParser().parseExpression(Subsection)) 189 return true; 190 } 191 192 getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags), 193 Subsection); 194 195 return false; 196 } 197 198 bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { 199 StringRef Name; 200 if (getParser().parseIdentifier(Name)) 201 return TokError("expected identifier in directive"); 202 MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name)); 203 204 if (getLexer().isNot(AsmToken::Comma)) 205 return TokError("unexpected token in directive"); 206 Lex(); 207 208 const MCExpr *Expr; 209 if (getParser().parseExpression(Expr)) 210 return true; 211 212 if (getLexer().isNot(AsmToken::EndOfStatement)) 213 return TokError("unexpected token in directive"); 214 215 getStreamer().emitELFSize(Sym, Expr); 216 return false; 217 } 218 219 bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { 220 // A section name can contain -, so we cannot just use 221 // parseIdentifier. 222 SMLoc FirstLoc = getLexer().getLoc(); 223 unsigned Size = 0; 224 225 if (getLexer().is(AsmToken::String)) { 226 SectionName = getTok().getIdentifier(); 227 Lex(); 228 return false; 229 } 230 231 for (;;) { 232 unsigned CurSize; 233 234 SMLoc PrevLoc = getLexer().getLoc(); 235 if (getLexer().is(AsmToken::Minus)) { 236 CurSize = 1; 237 Lex(); // Consume the "-". 238 } else if (getLexer().is(AsmToken::String)) { 239 CurSize = getTok().getIdentifier().size() + 2; 240 Lex(); 241 } else if (getLexer().is(AsmToken::Identifier)) { 242 CurSize = getTok().getIdentifier().size(); 243 Lex(); 244 } else { 245 break; 246 } 247 248 Size += CurSize; 249 SectionName = StringRef(FirstLoc.getPointer(), Size); 250 251 // Make sure the following token is adjacent. 252 if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) 253 break; 254 } 255 if (Size == 0) 256 return true; 257 258 return false; 259 } 260 261 static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) { 262 unsigned flags = 0; 263 264 for (unsigned i = 0; i < flagsStr.size(); i++) { 265 switch (flagsStr[i]) { 266 case 'a': 267 flags |= ELF::SHF_ALLOC; 268 break; 269 case 'e': 270 flags |= ELF::SHF_EXCLUDE; 271 break; 272 case 'x': 273 flags |= ELF::SHF_EXECINSTR; 274 break; 275 case 'w': 276 flags |= ELF::SHF_WRITE; 277 break; 278 case 'M': 279 flags |= ELF::SHF_MERGE; 280 break; 281 case 'S': 282 flags |= ELF::SHF_STRINGS; 283 break; 284 case 'T': 285 flags |= ELF::SHF_TLS; 286 break; 287 case 'c': 288 flags |= ELF::XCORE_SHF_CP_SECTION; 289 break; 290 case 'd': 291 flags |= ELF::XCORE_SHF_DP_SECTION; 292 break; 293 case 'G': 294 flags |= ELF::SHF_GROUP; 295 break; 296 case '?': 297 *UseLastGroup = true; 298 break; 299 default: 300 return -1U; 301 } 302 } 303 304 return flags; 305 } 306 307 unsigned ELFAsmParser::parseSunStyleSectionFlags() { 308 unsigned flags = 0; 309 while (getLexer().is(AsmToken::Hash)) { 310 Lex(); // Eat the #. 311 312 if (!getLexer().is(AsmToken::Identifier)) 313 return -1U; 314 315 StringRef flagId = getTok().getIdentifier(); 316 if (flagId == "alloc") 317 flags |= ELF::SHF_ALLOC; 318 else if (flagId == "execinstr") 319 flags |= ELF::SHF_EXECINSTR; 320 else if (flagId == "write") 321 flags |= ELF::SHF_WRITE; 322 else if (flagId == "tls") 323 flags |= ELF::SHF_TLS; 324 else 325 return -1U; 326 327 Lex(); // Eat the flag. 328 329 if (!getLexer().is(AsmToken::Comma)) 330 break; 331 Lex(); // Eat the comma. 332 } 333 return flags; 334 } 335 336 337 bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { 338 getStreamer().PushSection(); 339 340 if (ParseSectionArguments(/*IsPush=*/true, loc)) { 341 getStreamer().PopSection(); 342 return true; 343 } 344 345 return false; 346 } 347 348 bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { 349 if (!getStreamer().PopSection()) 350 return TokError(".popsection without corresponding .pushsection"); 351 return false; 352 } 353 354 // FIXME: This is a work in progress. 355 bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { 356 return ParseSectionArguments(/*IsPush=*/false, loc); 357 } 358 359 bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { 360 StringRef SectionName; 361 362 if (ParseSectionName(SectionName)) 363 return TokError("expected identifier in directive"); 364 365 StringRef TypeName; 366 int64_t Size = 0; 367 StringRef GroupName; 368 unsigned Flags = 0; 369 const MCExpr *Subsection = nullptr; 370 bool UseLastGroup = false; 371 StringRef UniqueStr; 372 int64_t UniqueID = ~0; 373 374 // Set the defaults first. 375 if (SectionName == ".fini" || SectionName == ".init" || 376 SectionName == ".rodata") 377 Flags |= ELF::SHF_ALLOC; 378 if (SectionName == ".fini" || SectionName == ".init") 379 Flags |= ELF::SHF_EXECINSTR; 380 381 if (getLexer().is(AsmToken::Comma)) { 382 Lex(); 383 384 if (IsPush && getLexer().isNot(AsmToken::String)) { 385 if (getParser().parseExpression(Subsection)) 386 return true; 387 if (getLexer().isNot(AsmToken::Comma)) 388 goto EndStmt; 389 Lex(); 390 } 391 392 unsigned extraFlags; 393 394 if (getLexer().isNot(AsmToken::String)) { 395 if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax() 396 || getLexer().isNot(AsmToken::Hash)) 397 return TokError("expected string in directive"); 398 extraFlags = parseSunStyleSectionFlags(); 399 } else { 400 StringRef FlagsStr = getTok().getStringContents(); 401 Lex(); 402 extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup); 403 } 404 405 if (extraFlags == -1U) 406 return TokError("unknown flag"); 407 Flags |= extraFlags; 408 409 bool Mergeable = Flags & ELF::SHF_MERGE; 410 bool Group = Flags & ELF::SHF_GROUP; 411 if (Group && UseLastGroup) 412 return TokError("Section cannot specifiy a group name while also acting " 413 "as a member of the last group"); 414 415 if (getLexer().isNot(AsmToken::Comma)) { 416 if (Mergeable) 417 return TokError("Mergeable section must specify the type"); 418 if (Group) 419 return TokError("Group section must specify the type"); 420 } else { 421 Lex(); 422 if (getLexer().is(AsmToken::At) || getLexer().is(AsmToken::Percent) || 423 getLexer().is(AsmToken::String)) { 424 if (!getLexer().is(AsmToken::String)) 425 Lex(); 426 } else 427 return TokError("expected '@<type>', '%<type>' or \"<type>\""); 428 429 if (getParser().parseIdentifier(TypeName)) 430 return TokError("expected identifier in directive"); 431 432 if (Mergeable) { 433 if (getLexer().isNot(AsmToken::Comma)) 434 return TokError("expected the entry size"); 435 Lex(); 436 if (getParser().parseAbsoluteExpression(Size)) 437 return true; 438 if (Size <= 0) 439 return TokError("entry size must be positive"); 440 } 441 442 if (Group) { 443 if (getLexer().isNot(AsmToken::Comma)) 444 return TokError("expected group name"); 445 Lex(); 446 if (getParser().parseIdentifier(GroupName)) 447 return true; 448 if (getLexer().is(AsmToken::Comma)) { 449 Lex(); 450 StringRef Linkage; 451 if (getParser().parseIdentifier(Linkage)) 452 return true; 453 if (Linkage != "comdat") 454 return TokError("Linkage must be 'comdat'"); 455 } 456 } 457 if (getLexer().is(AsmToken::Comma)) { 458 Lex(); 459 if (getParser().parseIdentifier(UniqueStr)) 460 return TokError("expected identifier in directive"); 461 if (UniqueStr != "unique") 462 return TokError("expected 'unique'"); 463 if (getLexer().isNot(AsmToken::Comma)) 464 return TokError("expected commma"); 465 Lex(); 466 if (getParser().parseAbsoluteExpression(UniqueID)) 467 return true; 468 if (UniqueID < 0) 469 return TokError("unique id must be positive"); 470 if (!isUInt<32>(UniqueID) || UniqueID == ~0U) 471 return TokError("unique id is too large"); 472 } 473 } 474 } 475 476 EndStmt: 477 if (getLexer().isNot(AsmToken::EndOfStatement)) 478 return TokError("unexpected token in directive"); 479 480 unsigned Type = ELF::SHT_PROGBITS; 481 482 if (TypeName.empty()) { 483 if (SectionName.startswith(".note")) 484 Type = ELF::SHT_NOTE; 485 else if (SectionName == ".init_array") 486 Type = ELF::SHT_INIT_ARRAY; 487 else if (SectionName == ".fini_array") 488 Type = ELF::SHT_FINI_ARRAY; 489 else if (SectionName == ".preinit_array") 490 Type = ELF::SHT_PREINIT_ARRAY; 491 } else { 492 if (TypeName == "init_array") 493 Type = ELF::SHT_INIT_ARRAY; 494 else if (TypeName == "fini_array") 495 Type = ELF::SHT_FINI_ARRAY; 496 else if (TypeName == "preinit_array") 497 Type = ELF::SHT_PREINIT_ARRAY; 498 else if (TypeName == "nobits") 499 Type = ELF::SHT_NOBITS; 500 else if (TypeName == "progbits") 501 Type = ELF::SHT_PROGBITS; 502 else if (TypeName == "note") 503 Type = ELF::SHT_NOTE; 504 else if (TypeName == "unwind") 505 Type = ELF::SHT_X86_64_UNWIND; 506 else 507 return TokError("unknown section type"); 508 } 509 510 if (UseLastGroup) { 511 MCSectionSubPair CurrentSection = getStreamer().getCurrentSection(); 512 if (const MCSectionELF *Section = 513 cast_or_null<MCSectionELF>(CurrentSection.first)) 514 if (const MCSymbol *Group = Section->getGroup()) { 515 GroupName = Group->getName(); 516 Flags |= ELF::SHF_GROUP; 517 } 518 } 519 520 MCSection *ELFSection = getContext().getELFSection(SectionName, Type, Flags, 521 Size, GroupName, UniqueID); 522 getStreamer().SwitchSection(ELFSection, Subsection); 523 524 if (getContext().getGenDwarfForAssembly()) { 525 bool InsertResult = getContext().addGenDwarfSection(ELFSection); 526 if (InsertResult) { 527 if (getContext().getDwarfVersion() <= 2) 528 Warning(loc, "DWARF2 only supports one section per compilation unit"); 529 530 if (!ELFSection->getBeginSymbol()) { 531 MCSymbol *SectionStartSymbol = getContext().createTempSymbol(); 532 getStreamer().EmitLabel(SectionStartSymbol); 533 ELFSection->setBeginSymbol(SectionStartSymbol); 534 } 535 } 536 } 537 538 return false; 539 } 540 541 bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { 542 MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); 543 if (PreviousSection.first == nullptr) 544 return TokError(".previous without corresponding .section"); 545 getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); 546 547 return false; 548 } 549 550 static MCSymbolAttr MCAttrForString(StringRef Type) { 551 return StringSwitch<MCSymbolAttr>(Type) 552 .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction) 553 .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject) 554 .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS) 555 .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon) 556 .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType) 557 .Cases("STT_GNU_IFUNC", "gnu_indirect_function", 558 MCSA_ELF_TypeIndFunction) 559 .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) 560 .Default(MCSA_Invalid); 561 } 562 563 /// ParseDirectiveELFType 564 /// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> 565 /// ::= .type identifier , #attribute 566 /// ::= .type identifier , @attribute 567 /// ::= .type identifier , %attribute 568 /// ::= .type identifier , "attribute" 569 bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 570 StringRef Name; 571 if (getParser().parseIdentifier(Name)) 572 return TokError("expected identifier in directive"); 573 574 // Handle the identifier as the key symbol. 575 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 576 577 // NOTE the comma is optional in all cases. It is only documented as being 578 // optional in the first case, however, GAS will silently treat the comma as 579 // optional in all cases. Furthermore, although the documentation states that 580 // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS 581 // accepts both the upper case name as well as the lower case aliases. 582 if (getLexer().is(AsmToken::Comma)) 583 Lex(); 584 585 if (getLexer().isNot(AsmToken::Identifier) && 586 getLexer().isNot(AsmToken::Hash) && 587 getLexer().isNot(AsmToken::Percent) && 588 getLexer().isNot(AsmToken::String)) { 589 if (!getLexer().getAllowAtInIdentifier()) 590 return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', " 591 "'%<type>' or \"<type>\""); 592 else if (getLexer().isNot(AsmToken::At)) 593 return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " 594 "'%<type>' or \"<type>\""); 595 } 596 597 if (getLexer().isNot(AsmToken::String) && 598 getLexer().isNot(AsmToken::Identifier)) 599 Lex(); 600 601 SMLoc TypeLoc = getLexer().getLoc(); 602 603 StringRef Type; 604 if (getParser().parseIdentifier(Type)) 605 return TokError("expected symbol type in directive"); 606 607 MCSymbolAttr Attr = MCAttrForString(Type); 608 if (Attr == MCSA_Invalid) 609 return Error(TypeLoc, "unsupported attribute in '.type' directive"); 610 611 if (getLexer().isNot(AsmToken::EndOfStatement)) 612 return TokError("unexpected token in '.type' directive"); 613 Lex(); 614 615 getStreamer().EmitSymbolAttribute(Sym, Attr); 616 617 return false; 618 } 619 620 /// ParseDirectiveIdent 621 /// ::= .ident string 622 bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { 623 if (getLexer().isNot(AsmToken::String)) 624 return TokError("unexpected token in '.ident' directive"); 625 626 StringRef Data = getTok().getIdentifier(); 627 628 Lex(); 629 630 getStreamer().EmitIdent(Data); 631 return false; 632 } 633 634 /// ParseDirectiveSymver 635 /// ::= .symver foo, bar2@zed 636 bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { 637 StringRef Name; 638 if (getParser().parseIdentifier(Name)) 639 return TokError("expected identifier in directive"); 640 641 if (getLexer().isNot(AsmToken::Comma)) 642 return TokError("expected a comma"); 643 644 // ARM assembly uses @ for a comment... 645 // except when parsing the second parameter of the .symver directive. 646 // Force the next symbol to allow @ in the identifier, which is 647 // required for this directive and then reset it to its initial state. 648 const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier(); 649 getLexer().setAllowAtInIdentifier(true); 650 Lex(); 651 getLexer().setAllowAtInIdentifier(AllowAtInIdentifier); 652 653 StringRef AliasName; 654 if (getParser().parseIdentifier(AliasName)) 655 return TokError("expected identifier in directive"); 656 657 if (AliasName.find('@') == StringRef::npos) 658 return TokError("expected a '@' in the name"); 659 660 MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); 661 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 662 const MCExpr *Value = MCSymbolRefExpr::create(Sym, getContext()); 663 664 getStreamer().EmitAssignment(Alias, Value); 665 return false; 666 } 667 668 /// ParseDirectiveVersion 669 /// ::= .version string 670 bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) { 671 if (getLexer().isNot(AsmToken::String)) 672 return TokError("unexpected token in '.version' directive"); 673 674 StringRef Data = getTok().getIdentifier(); 675 676 Lex(); 677 678 MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0); 679 680 getStreamer().PushSection(); 681 getStreamer().SwitchSection(Note); 682 getStreamer().EmitIntValue(Data.size()+1, 4); // namesz. 683 getStreamer().EmitIntValue(0, 4); // descsz = 0 (no description). 684 getStreamer().EmitIntValue(1, 4); // type = NT_VERSION. 685 getStreamer().EmitBytes(Data); // name. 686 getStreamer().EmitIntValue(0, 1); // terminate the string. 687 getStreamer().EmitValueToAlignment(4); // ensure 4 byte alignment. 688 getStreamer().PopSection(); 689 return false; 690 } 691 692 /// ParseDirectiveWeakref 693 /// ::= .weakref foo, bar 694 bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { 695 // FIXME: Share code with the other alias building directives. 696 697 StringRef AliasName; 698 if (getParser().parseIdentifier(AliasName)) 699 return TokError("expected identifier in directive"); 700 701 if (getLexer().isNot(AsmToken::Comma)) 702 return TokError("expected a comma"); 703 704 Lex(); 705 706 StringRef Name; 707 if (getParser().parseIdentifier(Name)) 708 return TokError("expected identifier in directive"); 709 710 MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); 711 712 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 713 714 getStreamer().EmitWeakReference(Alias, Sym); 715 return false; 716 } 717 718 bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { 719 const MCExpr *Subsection = nullptr; 720 if (getLexer().isNot(AsmToken::EndOfStatement)) { 721 if (getParser().parseExpression(Subsection)) 722 return true; 723 } 724 725 if (getLexer().isNot(AsmToken::EndOfStatement)) 726 return TokError("unexpected token in directive"); 727 728 getStreamer().SubSection(Subsection); 729 return false; 730 } 731 732 namespace llvm { 733 734 MCAsmParserExtension *createELFAsmParser() { 735 return new ELFAsmParser; 736 } 737 738 } 739