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