ELFAsmParser.cpp revision 484291c27319668ad99cb87def000254357736fb
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" 19using namespace llvm; 20 21namespace { 22 23class ELFAsmParser : public MCAsmParserExtension { 24 template<bool (ELFAsmParser::*Handler)(StringRef, SMLoc)> 25 void AddDirectiveHandler(StringRef Directive) { 26 getParser().AddDirectiveHandler(this, Directive, 27 HandleDirective<ELFAsmParser, Handler>); 28 } 29 30 bool ParseSectionSwitch(StringRef Section, unsigned Type, 31 unsigned Flags, SectionKind Kind); 32 33public: 34 ELFAsmParser() {} 35 36 virtual void Initialize(MCAsmParser &Parser) { 37 // Call the base implementation. 38 this->MCAsmParserExtension::Initialize(Parser); 39 40 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); 41 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); 42 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); 43 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); 44 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); 45 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); 46 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); 47 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); 48 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local"); 49 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); 50 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); 51 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); 52 AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); 53 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); 54 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); 55 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); 56 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); 57 } 58 59 // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is 60 // the best way for us to get access to it? 61 bool ParseSectionDirectiveData(StringRef, SMLoc) { 62 return ParseSectionSwitch(".data", MCSectionELF::SHT_PROGBITS, 63 MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, 64 SectionKind::getDataRel()); 65 } 66 bool ParseSectionDirectiveText(StringRef, SMLoc) { 67 return ParseSectionSwitch(".text", MCSectionELF::SHT_PROGBITS, 68 MCSectionELF::SHF_EXECINSTR | 69 MCSectionELF::SHF_ALLOC, SectionKind::getText()); 70 } 71 bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 72 return ParseSectionSwitch(".bss", MCSectionELF::SHT_NOBITS, 73 MCSectionELF::SHF_WRITE | 74 MCSectionELF::SHF_ALLOC, SectionKind::getBSS()); 75 } 76 bool ParseSectionDirectiveRoData(StringRef, SMLoc) { 77 return ParseSectionSwitch(".rodata", MCSectionELF::SHT_PROGBITS, 78 MCSectionELF::SHF_ALLOC, 79 SectionKind::getReadOnly()); 80 } 81 bool ParseSectionDirectiveTData(StringRef, SMLoc) { 82 return ParseSectionSwitch(".tdata", MCSectionELF::SHT_PROGBITS, 83 MCSectionELF::SHF_ALLOC | 84 MCSectionELF::SHF_TLS | MCSectionELF::SHF_WRITE, 85 SectionKind::getThreadData()); 86 } 87 bool ParseSectionDirectiveTBSS(StringRef, SMLoc) { 88 return ParseSectionSwitch(".tbss", MCSectionELF::SHT_NOBITS, 89 MCSectionELF::SHF_ALLOC | 90 MCSectionELF::SHF_TLS | MCSectionELF::SHF_WRITE, 91 SectionKind::getThreadBSS()); 92 } 93 bool ParseSectionDirectiveDataRel(StringRef, SMLoc) { 94 return ParseSectionSwitch(".data.rel", MCSectionELF::SHT_PROGBITS, 95 MCSectionELF::SHF_ALLOC | 96 MCSectionELF::SHF_WRITE, 97 SectionKind::getDataRel()); 98 } 99 bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { 100 return ParseSectionSwitch(".data.rel.ro", MCSectionELF::SHT_PROGBITS, 101 MCSectionELF::SHF_ALLOC | 102 MCSectionELF::SHF_WRITE, 103 SectionKind::getReadOnlyWithRel()); 104 } 105 bool ParseSectionDirectiveDataRelRoLocal(StringRef, SMLoc) { 106 return ParseSectionSwitch(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS, 107 MCSectionELF::SHF_ALLOC | 108 MCSectionELF::SHF_WRITE, 109 SectionKind::getReadOnlyWithRelLocal()); 110 } 111 bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { 112 return ParseSectionSwitch(".eh_frame", MCSectionELF::SHT_PROGBITS, 113 MCSectionELF::SHF_ALLOC | 114 MCSectionELF::SHF_WRITE, 115 SectionKind::getDataRel()); 116 } 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 ParseDirectiveWeakref(StringRef, SMLoc); 124 125private: 126 bool ParseSectionName(StringRef &SectionName); 127}; 128 129} 130 131bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, 132 unsigned Flags, SectionKind Kind) { 133 if (getLexer().isNot(AsmToken::EndOfStatement)) 134 return TokError("unexpected token in section switching directive"); 135 Lex(); 136 137 getStreamer().SwitchSection(getContext().getELFSection( 138 Section, Type, Flags, Kind)); 139 140 return false; 141} 142 143bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { 144 StringRef Name; 145 if (getParser().ParseIdentifier(Name)) 146 return TokError("expected identifier in directive"); 147 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);; 148 149 if (getLexer().isNot(AsmToken::Comma)) 150 return TokError("unexpected token in directive"); 151 Lex(); 152 153 const MCExpr *Expr; 154 if (getParser().ParseExpression(Expr)) 155 return true; 156 157 if (getLexer().isNot(AsmToken::EndOfStatement)) 158 return TokError("unexpected token in directive"); 159 160 getStreamer().EmitELFSize(Sym, Expr); 161 return false; 162} 163 164bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { 165 // A section name can contain -, so we cannot just use 166 // ParseIdentifier. 167 SMLoc FirstLoc = getLexer().getLoc(); 168 unsigned Size = 0; 169 170 for (;;) { 171 StringRef Tmp; 172 unsigned CurSize; 173 174 SMLoc PrevLoc = getLexer().getLoc(); 175 if (getLexer().is(AsmToken::Minus)) { 176 CurSize = 1; 177 Lex(); // Consume the "-". 178 } else if (!getParser().ParseIdentifier(Tmp)) 179 CurSize = Tmp.size(); 180 else 181 break; 182 183 Size += CurSize; 184 SectionName = StringRef(FirstLoc.getPointer(), Size); 185 186 // Make sure the following token is adjacent. 187 if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) 188 break; 189 } 190 if (Size == 0) 191 return true; 192 193 return false; 194} 195 196// FIXME: This is a work in progress. 197bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 198 StringRef SectionName; 199 200 if (ParseSectionName(SectionName)) 201 return TokError("expected identifier in directive"); 202 203 StringRef FlagsStr; 204 StringRef TypeName; 205 int64_t Size = 0; 206 if (getLexer().is(AsmToken::Comma)) { 207 Lex(); 208 209 if (getLexer().isNot(AsmToken::String)) 210 return TokError("expected string in directive"); 211 212 FlagsStr = getTok().getStringContents(); 213 Lex(); 214 215 AsmToken::TokenKind TypeStartToken; 216 if (getContext().getAsmInfo().getCommentString()[0] == '@') 217 TypeStartToken = AsmToken::Percent; 218 else 219 TypeStartToken = AsmToken::At; 220 221 bool Mergeable = FlagsStr.find('M') != StringRef::npos; 222 bool Group = FlagsStr.find('G') != StringRef::npos; 223 224 if (getLexer().isNot(AsmToken::Comma)) { 225 if (Mergeable) 226 return TokError("Mergeable section must specify the type"); 227 if (Group) 228 return TokError("Group section must specify the type"); 229 } else { 230 Lex(); 231 if (getLexer().isNot(TypeStartToken)) 232 return TokError("expected the type"); 233 234 Lex(); 235 if (getParser().ParseIdentifier(TypeName)) 236 return TokError("expected identifier in directive"); 237 238 if (Mergeable) { 239 if (getLexer().isNot(AsmToken::Comma)) 240 return TokError("expected the entry size"); 241 Lex(); 242 if (getParser().ParseAbsoluteExpression(Size)) 243 return true; 244 if (Size <= 0) 245 return TokError("entry size must be positive"); 246 } 247 248 if (Group) { 249 if (getLexer().isNot(AsmToken::Comma)) 250 return TokError("expected group name"); 251 Lex(); 252 StringRef GroupName; 253 if (getParser().ParseIdentifier(GroupName)) 254 return true; 255 if (getLexer().is(AsmToken::Comma)) { 256 Lex(); 257 StringRef Linkage; 258 if (getParser().ParseIdentifier(Linkage)) 259 return true; 260 if (Linkage != "comdat" && Linkage != ".gnu.linkonce") 261 return TokError("Linkage must be 'comdat' or '.gnu.linkonce'"); 262 } 263 } 264 } 265 } 266 267 if (getLexer().isNot(AsmToken::EndOfStatement)) 268 return TokError("unexpected token in directive"); 269 270 unsigned Flags = 0; 271 unsigned Type = MCSectionELF::SHT_NULL; 272 273 // Set the defaults first. 274 if (SectionName == ".fini" || SectionName == ".init") { 275 Type = MCSectionELF::SHT_PROGBITS; 276 Flags |= MCSectionELF::SHF_ALLOC; 277 Flags |= MCSectionELF::SHF_EXECINSTR; 278 } 279 280 for (unsigned i = 0; i < FlagsStr.size(); i++) { 281 switch (FlagsStr[i]) { 282 case 'a': 283 Flags |= MCSectionELF::SHF_ALLOC; 284 break; 285 case 'x': 286 Flags |= MCSectionELF::SHF_EXECINSTR; 287 break; 288 case 'w': 289 Flags |= MCSectionELF::SHF_WRITE; 290 break; 291 case 'M': 292 Flags |= MCSectionELF::SHF_MERGE; 293 break; 294 case 'S': 295 Flags |= MCSectionELF::SHF_STRINGS; 296 break; 297 case 'T': 298 Flags |= MCSectionELF::SHF_TLS; 299 break; 300 case 'c': 301 Flags |= MCSectionELF::XCORE_SHF_CP_SECTION; 302 break; 303 case 'd': 304 Flags |= MCSectionELF::XCORE_SHF_DP_SECTION; 305 break; 306 case 'G': 307 break; 308 default: 309 return TokError("unknown flag"); 310 } 311 } 312 313 if (!TypeName.empty()) { 314 if (TypeName == "init_array") 315 Type = MCSectionELF::SHT_INIT_ARRAY; 316 else if (TypeName == "fini_array") 317 Type = MCSectionELF::SHT_FINI_ARRAY; 318 else if (TypeName == "preinit_array") 319 Type = MCSectionELF::SHT_PREINIT_ARRAY; 320 else if (TypeName == "nobits") 321 Type = MCSectionELF::SHT_NOBITS; 322 else if (TypeName == "progbits") 323 Type = MCSectionELF::SHT_PROGBITS; 324 else 325 return TokError("unknown section type"); 326 } 327 328 SectionKind Kind = (Flags & MCSectionELF::SHF_EXECINSTR) 329 ? SectionKind::getText() 330 : SectionKind::getDataRel(); 331 getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, 332 Flags, Kind, false, 333 Size)); 334 return false; 335} 336 337bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { 338 const MCSection *PreviousSection = getStreamer().getPreviousSection(); 339 if (PreviousSection != NULL) 340 getStreamer().SwitchSection(PreviousSection); 341 342 return false; 343} 344 345/// ParseDirectiveELFType 346/// ::= .type identifier , @attribute 347bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 348 StringRef Name; 349 if (getParser().ParseIdentifier(Name)) 350 return TokError("expected identifier in directive"); 351 352 // Handle the identifier as the key symbol. 353 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 354 355 if (getLexer().isNot(AsmToken::Comma)) 356 return TokError("unexpected token in '.type' directive"); 357 Lex(); 358 359 if (getLexer().isNot(AsmToken::At)) 360 return TokError("expected '@' before type"); 361 Lex(); 362 363 StringRef Type; 364 SMLoc TypeLoc; 365 366 TypeLoc = getLexer().getLoc(); 367 if (getParser().ParseIdentifier(Type)) 368 return TokError("expected symbol type in directive"); 369 370 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type) 371 .Case("function", MCSA_ELF_TypeFunction) 372 .Case("object", MCSA_ELF_TypeObject) 373 .Case("tls_object", MCSA_ELF_TypeTLS) 374 .Case("common", MCSA_ELF_TypeCommon) 375 .Case("notype", MCSA_ELF_TypeNoType) 376 .Default(MCSA_Invalid); 377 378 if (Attr == MCSA_Invalid) 379 return Error(TypeLoc, "unsupported attribute in '.type' directive"); 380 381 if (getLexer().isNot(AsmToken::EndOfStatement)) 382 return TokError("unexpected token in '.type' directive"); 383 384 Lex(); 385 386 getStreamer().EmitSymbolAttribute(Sym, Attr); 387 388 return false; 389} 390 391/// ParseDirectiveIdent 392/// ::= .ident string 393bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { 394 if (getLexer().isNot(AsmToken::String)) 395 return TokError("unexpected token in '.ident' directive"); 396 397 StringRef Data = getTok().getIdentifier(); 398 399 Lex(); 400 401 const MCSection *OldSection = getStreamer().getCurrentSection(); 402 const MCSection *Comment = 403 getContext().getELFSection(".comment", MCSectionELF::SHT_PROGBITS, 404 MCSectionELF::SHF_MERGE | 405 MCSectionELF::SHF_STRINGS, 406 SectionKind::getReadOnly(), 407 false, 1); 408 409 static bool First = true; 410 411 getStreamer().SwitchSection(Comment); 412 if (First) 413 getStreamer().EmitIntValue(0, 1); 414 First = false; 415 getStreamer().EmitBytes(Data, 0); 416 getStreamer().EmitIntValue(0, 1); 417 getStreamer().SwitchSection(OldSection); 418 return false; 419} 420 421/// ParseDirectiveSymver 422/// ::= .symver foo, bar2@zed 423bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { 424 StringRef Name; 425 if (getParser().ParseIdentifier(Name)) 426 return TokError("expected identifier in directive"); 427 428 if (getLexer().isNot(AsmToken::Comma)) 429 return TokError("expected a comma"); 430 431 Lex(); 432 433 StringRef AliasName; 434 if (getParser().ParseIdentifier(AliasName)) 435 return TokError("expected identifier in directive"); 436 437 if (AliasName.find('@') == StringRef::npos) 438 return TokError("expected a '@' in the name"); 439 440 MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); 441 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 442 const MCExpr *Value = MCSymbolRefExpr::Create(Sym, getContext()); 443 444 getStreamer().EmitAssignment(Alias, Value); 445 return false; 446} 447 448/// ParseDirectiveWeakref 449/// ::= .weakref foo, bar 450bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { 451 // FIXME: Share code with the other alias building directives. 452 453 StringRef AliasName; 454 if (getParser().ParseIdentifier(AliasName)) 455 return TokError("expected identifier in directive"); 456 457 if (getLexer().isNot(AsmToken::Comma)) 458 return TokError("expected a comma"); 459 460 Lex(); 461 462 StringRef Name; 463 if (getParser().ParseIdentifier(Name)) 464 return TokError("expected identifier in directive"); 465 466 MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); 467 468 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 469 470 getStreamer().EmitWeakReference(Alias, Sym); 471 return false; 472} 473 474namespace llvm { 475 476MCAsmParserExtension *createELFAsmParser() { 477 return new ELFAsmParser; 478} 479 480} 481