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/Support/ELF.h" 20using namespace llvm; 21 22namespace { 23 24class ELFAsmParser : public MCAsmParserExtension { 25 template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)> 26 void addDirectiveHandler(StringRef Directive) { 27 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 28 this, HandleDirective<ELFAsmParser, HandlerMethod>); 29 30 getParser().addDirectiveHandler(Directive, Handler); 31 } 32 33 bool ParseSectionSwitch(StringRef Section, unsigned Type, 34 unsigned Flags, SectionKind Kind); 35 bool SeenIdent; 36 37public: 38 ELFAsmParser() : SeenIdent(false) { 39 BracketExpressionsSupported = true; 40 } 41 42 virtual void Initialize(MCAsmParser &Parser) { 43 // Call the base implementation. 44 this->MCAsmParserExtension::Initialize(Parser); 45 46 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); 47 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); 48 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); 49 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); 50 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); 51 addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); 52 addDirectiveHandler< 53 &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); 54 addDirectiveHandler< 55 &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); 56 addDirectiveHandler< 57 &ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local"); 58 addDirectiveHandler< 59 &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); 60 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); 61 addDirectiveHandler< 62 &ELFAsmParser::ParseDirectivePushSection>(".pushsection"); 63 addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); 64 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); 65 addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); 66 addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); 67 addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); 68 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); 69 addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version"); 70 addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); 71 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); 72 addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); 73 addDirectiveHandler< 74 &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected"); 75 addDirectiveHandler< 76 &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); 77 addDirectiveHandler< 78 &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); 79 } 80 81 // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is 82 // 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::getDataRel()); 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 ParseSectionDirectiveDataRel(StringRef, SMLoc) { 116 return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS, 117 ELF::SHF_ALLOC | 118 ELF::SHF_WRITE, 119 SectionKind::getDataRel()); 120 } 121 bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { 122 return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS, 123 ELF::SHF_ALLOC | 124 ELF::SHF_WRITE, 125 SectionKind::getReadOnlyWithRel()); 126 } 127 bool ParseSectionDirectiveDataRelRoLocal(StringRef, SMLoc) { 128 return ParseSectionSwitch(".data.rel.ro.local", ELF::SHT_PROGBITS, 129 ELF::SHF_ALLOC | 130 ELF::SHF_WRITE, 131 SectionKind::getReadOnlyWithRelLocal()); 132 } 133 bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { 134 return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS, 135 ELF::SHF_ALLOC | 136 ELF::SHF_WRITE, 137 SectionKind::getDataRel()); 138 } 139 bool ParseDirectivePushSection(StringRef, SMLoc); 140 bool ParseDirectivePopSection(StringRef, SMLoc); 141 bool ParseDirectiveSection(StringRef, SMLoc); 142 bool ParseDirectiveSize(StringRef, SMLoc); 143 bool ParseDirectivePrevious(StringRef, SMLoc); 144 bool ParseDirectiveType(StringRef, SMLoc); 145 bool ParseDirectiveIdent(StringRef, SMLoc); 146 bool ParseDirectiveSymver(StringRef, SMLoc); 147 bool ParseDirectiveVersion(StringRef, SMLoc); 148 bool ParseDirectiveWeakref(StringRef, SMLoc); 149 bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); 150 151private: 152 bool ParseSectionName(StringRef &SectionName); 153}; 154 155} 156 157/// ParseDirectiveSymbolAttribute 158/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] 159bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { 160 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) 161 .Case(".weak", MCSA_Weak) 162 .Case(".local", MCSA_Local) 163 .Case(".hidden", MCSA_Hidden) 164 .Case(".internal", MCSA_Internal) 165 .Case(".protected", MCSA_Protected) 166 .Default(MCSA_Invalid); 167 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); 168 if (getLexer().isNot(AsmToken::EndOfStatement)) { 169 for (;;) { 170 StringRef Name; 171 172 if (getParser().parseIdentifier(Name)) 173 return TokError("expected identifier in directive"); 174 175 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 176 177 getStreamer().EmitSymbolAttribute(Sym, Attr); 178 179 if (getLexer().is(AsmToken::EndOfStatement)) 180 break; 181 182 if (getLexer().isNot(AsmToken::Comma)) 183 return TokError("unexpected token in directive"); 184 Lex(); 185 } 186 } 187 188 Lex(); 189 return false; 190} 191 192bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, 193 unsigned Flags, SectionKind Kind) { 194 if (getLexer().isNot(AsmToken::EndOfStatement)) 195 return TokError("unexpected token in section switching directive"); 196 Lex(); 197 198 getStreamer().SwitchSection(getContext().getELFSection( 199 Section, Type, Flags, Kind)); 200 201 return false; 202} 203 204bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { 205 StringRef Name; 206 if (getParser().parseIdentifier(Name)) 207 return TokError("expected identifier in directive"); 208 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 209 210 if (getLexer().isNot(AsmToken::Comma)) 211 return TokError("unexpected token in directive"); 212 Lex(); 213 214 const MCExpr *Expr; 215 if (getParser().parseExpression(Expr)) 216 return true; 217 218 if (getLexer().isNot(AsmToken::EndOfStatement)) 219 return TokError("unexpected token in directive"); 220 221 getStreamer().EmitELFSize(Sym, Expr); 222 return false; 223} 224 225bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { 226 // A section name can contain -, so we cannot just use 227 // parseIdentifier. 228 SMLoc FirstLoc = getLexer().getLoc(); 229 unsigned Size = 0; 230 231 if (getLexer().is(AsmToken::String)) { 232 SectionName = getTok().getIdentifier(); 233 Lex(); 234 return false; 235 } 236 237 for (;;) { 238 StringRef Tmp; 239 unsigned CurSize; 240 241 SMLoc PrevLoc = getLexer().getLoc(); 242 if (getLexer().is(AsmToken::Minus)) { 243 CurSize = 1; 244 Lex(); // Consume the "-". 245 } else if (getLexer().is(AsmToken::String)) { 246 CurSize = getTok().getIdentifier().size() + 2; 247 Lex(); 248 } else if (getLexer().is(AsmToken::Identifier)) { 249 CurSize = getTok().getIdentifier().size(); 250 Lex(); 251 } else { 252 break; 253 } 254 255 Size += CurSize; 256 SectionName = StringRef(FirstLoc.getPointer(), Size); 257 258 // Make sure the following token is adjacent. 259 if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) 260 break; 261 } 262 if (Size == 0) 263 return true; 264 265 return false; 266} 267 268static SectionKind computeSectionKind(unsigned Flags) { 269 if (Flags & ELF::SHF_EXECINSTR) 270 return SectionKind::getText(); 271 if (Flags & ELF::SHF_TLS) 272 return SectionKind::getThreadData(); 273 return SectionKind::getDataRel(); 274} 275 276static int parseSectionFlags(StringRef flagsStr) { 277 int flags = 0; 278 279 for (unsigned i = 0; i < flagsStr.size(); i++) { 280 switch (flagsStr[i]) { 281 case 'a': 282 flags |= ELF::SHF_ALLOC; 283 break; 284 case 'x': 285 flags |= ELF::SHF_EXECINSTR; 286 break; 287 case 'w': 288 flags |= ELF::SHF_WRITE; 289 break; 290 case 'M': 291 flags |= ELF::SHF_MERGE; 292 break; 293 case 'S': 294 flags |= ELF::SHF_STRINGS; 295 break; 296 case 'T': 297 flags |= ELF::SHF_TLS; 298 break; 299 case 'c': 300 flags |= ELF::XCORE_SHF_CP_SECTION; 301 break; 302 case 'd': 303 flags |= ELF::XCORE_SHF_DP_SECTION; 304 break; 305 case 'G': 306 flags |= ELF::SHF_GROUP; 307 break; 308 default: 309 return -1; 310 } 311 } 312 313 return flags; 314} 315 316bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { 317 getStreamer().PushSection(); 318 319 if (ParseDirectiveSection(s, loc)) { 320 getStreamer().PopSection(); 321 return true; 322 } 323 324 return false; 325} 326 327bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { 328 if (!getStreamer().PopSection()) 329 return TokError(".popsection without corresponding .pushsection"); 330 return false; 331} 332 333// FIXME: This is a work in progress. 334bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 335 StringRef SectionName; 336 337 if (ParseSectionName(SectionName)) 338 return TokError("expected identifier in directive"); 339 340 StringRef TypeName; 341 int64_t Size = 0; 342 StringRef GroupName; 343 unsigned Flags = 0; 344 345 // Set the defaults first. 346 if (SectionName == ".fini" || SectionName == ".init" || 347 SectionName == ".rodata") 348 Flags |= ELF::SHF_ALLOC; 349 if (SectionName == ".fini" || SectionName == ".init") 350 Flags |= ELF::SHF_EXECINSTR; 351 352 if (getLexer().is(AsmToken::Comma)) { 353 Lex(); 354 355 if (getLexer().isNot(AsmToken::String)) 356 return TokError("expected string in directive"); 357 358 StringRef FlagsStr = getTok().getStringContents(); 359 Lex(); 360 361 int extraFlags = parseSectionFlags(FlagsStr); 362 if (extraFlags < 0) 363 return TokError("unknown flag"); 364 Flags |= extraFlags; 365 366 bool Mergeable = Flags & ELF::SHF_MERGE; 367 bool Group = Flags & ELF::SHF_GROUP; 368 369 if (getLexer().isNot(AsmToken::Comma)) { 370 if (Mergeable) 371 return TokError("Mergeable section must specify the type"); 372 if (Group) 373 return TokError("Group section must specify the type"); 374 } else { 375 Lex(); 376 if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) 377 return TokError("expected '@' or '%' before type"); 378 379 Lex(); 380 if (getParser().parseIdentifier(TypeName)) 381 return TokError("expected identifier in directive"); 382 383 if (Mergeable) { 384 if (getLexer().isNot(AsmToken::Comma)) 385 return TokError("expected the entry size"); 386 Lex(); 387 if (getParser().parseAbsoluteExpression(Size)) 388 return true; 389 if (Size <= 0) 390 return TokError("entry size must be positive"); 391 } 392 393 if (Group) { 394 if (getLexer().isNot(AsmToken::Comma)) 395 return TokError("expected group name"); 396 Lex(); 397 if (getParser().parseIdentifier(GroupName)) 398 return true; 399 if (getLexer().is(AsmToken::Comma)) { 400 Lex(); 401 StringRef Linkage; 402 if (getParser().parseIdentifier(Linkage)) 403 return true; 404 if (Linkage != "comdat") 405 return TokError("Linkage must be 'comdat'"); 406 } 407 } 408 } 409 } 410 411 if (getLexer().isNot(AsmToken::EndOfStatement)) 412 return TokError("unexpected token in directive"); 413 414 unsigned Type = ELF::SHT_PROGBITS; 415 416 if (TypeName.empty()) { 417 if (SectionName.startswith(".note")) 418 Type = ELF::SHT_NOTE; 419 else if (SectionName == ".init_array") 420 Type = ELF::SHT_INIT_ARRAY; 421 else if (SectionName == ".fini_array") 422 Type = ELF::SHT_FINI_ARRAY; 423 else if (SectionName == ".preinit_array") 424 Type = ELF::SHT_PREINIT_ARRAY; 425 } else { 426 if (TypeName == "init_array") 427 Type = ELF::SHT_INIT_ARRAY; 428 else if (TypeName == "fini_array") 429 Type = ELF::SHT_FINI_ARRAY; 430 else if (TypeName == "preinit_array") 431 Type = ELF::SHT_PREINIT_ARRAY; 432 else if (TypeName == "nobits") 433 Type = ELF::SHT_NOBITS; 434 else if (TypeName == "progbits") 435 Type = ELF::SHT_PROGBITS; 436 else if (TypeName == "note") 437 Type = ELF::SHT_NOTE; 438 else if (TypeName == "unwind") 439 Type = ELF::SHT_X86_64_UNWIND; 440 else 441 return TokError("unknown section type"); 442 } 443 444 SectionKind Kind = computeSectionKind(Flags); 445 getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, 446 Flags, Kind, Size, 447 GroupName)); 448 return false; 449} 450 451bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { 452 const MCSection *PreviousSection = getStreamer().getPreviousSection(); 453 if (PreviousSection == NULL) 454 return TokError(".previous without corresponding .section"); 455 getStreamer().SwitchSection(PreviousSection); 456 457 return false; 458} 459 460/// ParseDirectiveELFType 461/// ::= .type identifier , @attribute 462bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 463 StringRef Name; 464 if (getParser().parseIdentifier(Name)) 465 return TokError("expected identifier in directive"); 466 467 // Handle the identifier as the key symbol. 468 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 469 470 if (getLexer().isNot(AsmToken::Comma)) 471 return TokError("unexpected token in '.type' directive"); 472 Lex(); 473 474 if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) 475 return TokError("expected '@' or '%' before type"); 476 Lex(); 477 478 StringRef Type; 479 SMLoc TypeLoc; 480 481 TypeLoc = getLexer().getLoc(); 482 if (getParser().parseIdentifier(Type)) 483 return TokError("expected symbol type in directive"); 484 485 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type) 486 .Case("function", MCSA_ELF_TypeFunction) 487 .Case("object", MCSA_ELF_TypeObject) 488 .Case("tls_object", MCSA_ELF_TypeTLS) 489 .Case("common", MCSA_ELF_TypeCommon) 490 .Case("notype", MCSA_ELF_TypeNoType) 491 .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) 492 .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction) 493 .Default(MCSA_Invalid); 494 495 if (Attr == MCSA_Invalid) 496 return Error(TypeLoc, "unsupported attribute in '.type' directive"); 497 498 if (getLexer().isNot(AsmToken::EndOfStatement)) 499 return TokError("unexpected token in '.type' directive"); 500 501 Lex(); 502 503 getStreamer().EmitSymbolAttribute(Sym, Attr); 504 505 return false; 506} 507 508/// ParseDirectiveIdent 509/// ::= .ident string 510bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { 511 if (getLexer().isNot(AsmToken::String)) 512 return TokError("unexpected token in '.ident' directive"); 513 514 StringRef Data = getTok().getIdentifier(); 515 516 Lex(); 517 518 const MCSection *Comment = 519 getContext().getELFSection(".comment", ELF::SHT_PROGBITS, 520 ELF::SHF_MERGE | 521 ELF::SHF_STRINGS, 522 SectionKind::getReadOnly(), 523 1, ""); 524 525 getStreamer().PushSection(); 526 getStreamer().SwitchSection(Comment); 527 if (!SeenIdent) { 528 getStreamer().EmitIntValue(0, 1); 529 SeenIdent = true; 530 } 531 getStreamer().EmitBytes(Data); 532 getStreamer().EmitIntValue(0, 1); 533 getStreamer().PopSection(); 534 return false; 535} 536 537/// ParseDirectiveSymver 538/// ::= .symver foo, bar2@zed 539bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { 540 StringRef Name; 541 if (getParser().parseIdentifier(Name)) 542 return TokError("expected identifier in directive"); 543 544 if (getLexer().isNot(AsmToken::Comma)) 545 return TokError("expected a comma"); 546 547 Lex(); 548 549 StringRef AliasName; 550 if (getParser().parseIdentifier(AliasName)) 551 return TokError("expected identifier in directive"); 552 553 if (AliasName.find('@') == StringRef::npos) 554 return TokError("expected a '@' in the name"); 555 556 MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); 557 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 558 const MCExpr *Value = MCSymbolRefExpr::Create(Sym, getContext()); 559 560 getStreamer().EmitAssignment(Alias, Value); 561 return false; 562} 563 564/// ParseDirectiveVersion 565/// ::= .version string 566bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) { 567 if (getLexer().isNot(AsmToken::String)) 568 return TokError("unexpected token in '.version' directive"); 569 570 StringRef Data = getTok().getIdentifier(); 571 572 Lex(); 573 574 const MCSection *Note = 575 getContext().getELFSection(".note", ELF::SHT_NOTE, 0, 576 SectionKind::getReadOnly()); 577 578 getStreamer().PushSection(); 579 getStreamer().SwitchSection(Note); 580 getStreamer().EmitIntValue(Data.size()+1, 4); // namesz. 581 getStreamer().EmitIntValue(0, 4); // descsz = 0 (no description). 582 getStreamer().EmitIntValue(1, 4); // type = NT_VERSION. 583 getStreamer().EmitBytes(Data); // name. 584 getStreamer().EmitIntValue(0, 1); // terminate the string. 585 getStreamer().EmitValueToAlignment(4); // ensure 4 byte alignment. 586 getStreamer().PopSection(); 587 return false; 588} 589 590/// ParseDirectiveWeakref 591/// ::= .weakref foo, bar 592bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { 593 // FIXME: Share code with the other alias building directives. 594 595 StringRef AliasName; 596 if (getParser().parseIdentifier(AliasName)) 597 return TokError("expected identifier in directive"); 598 599 if (getLexer().isNot(AsmToken::Comma)) 600 return TokError("expected a comma"); 601 602 Lex(); 603 604 StringRef Name; 605 if (getParser().parseIdentifier(Name)) 606 return TokError("expected identifier in directive"); 607 608 MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); 609 610 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 611 612 getStreamer().EmitWeakReference(Alias, Sym); 613 return false; 614} 615 616namespace llvm { 617 618MCAsmParserExtension *createELFAsmParser() { 619 return new ELFAsmParser; 620} 621 622} 623