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