ELFAsmParser.cpp revision e90ea139f47752eb122af756a5714ef0b3756298
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/MCParser/MCAsmLexer.h" 16#include "llvm/MC/MCSectionELF.h" 17#include "llvm/MC/MCStreamer.h" 18using namespace llvm; 19 20namespace { 21 22class ELFAsmParser : public MCAsmParserExtension { 23 template<bool (ELFAsmParser::*Handler)(StringRef, SMLoc)> 24 void AddDirectiveHandler(StringRef Directive) { 25 getParser().AddDirectiveHandler(this, Directive, 26 HandleDirective<ELFAsmParser, Handler>); 27 } 28 29 bool ParseSectionSwitch(StringRef Section, unsigned Type, 30 unsigned Flags, SectionKind Kind); 31 32public: 33 ELFAsmParser() {} 34 35 virtual void Initialize(MCAsmParser &Parser) { 36 // Call the base implementation. 37 this->MCAsmParserExtension::Initialize(Parser); 38 39 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); 40 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); 41 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); 42 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); 43 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); 44 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); 45 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); 46 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); 47 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local"); 48 AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); 49 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); 50 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); 51 AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); 52 AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); 53 } 54 55 // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is 56 // the best way for us to get access to it? 57 bool ParseSectionDirectiveData(StringRef, SMLoc) { 58 return ParseSectionSwitch(".data", MCSectionELF::SHT_PROGBITS, 59 MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, 60 SectionKind::getDataRel()); 61 } 62 bool ParseSectionDirectiveText(StringRef, SMLoc) { 63 return ParseSectionSwitch(".text", MCSectionELF::SHT_PROGBITS, 64 MCSectionELF::SHF_EXECINSTR | 65 MCSectionELF::SHF_ALLOC, SectionKind::getText()); 66 } 67 bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 68 return ParseSectionSwitch(".bss", MCSectionELF::SHT_NOBITS, 69 MCSectionELF::SHF_WRITE | 70 MCSectionELF::SHF_ALLOC, SectionKind::getBSS()); 71 } 72 bool ParseSectionDirectiveRoData(StringRef, SMLoc) { 73 return ParseSectionSwitch(".rodata", MCSectionELF::SHT_PROGBITS, 74 MCSectionELF::SHF_ALLOC, 75 SectionKind::getReadOnly()); 76 } 77 bool ParseSectionDirectiveTData(StringRef, SMLoc) { 78 return ParseSectionSwitch(".tdata", MCSectionELF::SHT_PROGBITS, 79 MCSectionELF::SHF_ALLOC | 80 MCSectionELF::SHF_TLS | MCSectionELF::SHF_WRITE, 81 SectionKind::getThreadData()); 82 } 83 bool ParseSectionDirectiveTBSS(StringRef, SMLoc) { 84 return ParseSectionSwitch(".tbss", MCSectionELF::SHT_NOBITS, 85 MCSectionELF::SHF_ALLOC | 86 MCSectionELF::SHF_TLS | MCSectionELF::SHF_WRITE, 87 SectionKind::getThreadBSS()); 88 } 89 bool ParseSectionDirectiveDataRel(StringRef, SMLoc) { 90 return ParseSectionSwitch(".data.rel", MCSectionELF::SHT_PROGBITS, 91 MCSectionELF::SHF_ALLOC | 92 MCSectionELF::SHF_WRITE, 93 SectionKind::getDataRel()); 94 } 95 bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { 96 return ParseSectionSwitch(".data.rel.ro", MCSectionELF::SHT_PROGBITS, 97 MCSectionELF::SHF_ALLOC | 98 MCSectionELF::SHF_WRITE, 99 SectionKind::getReadOnlyWithRel()); 100 } 101 bool ParseSectionDirectiveDataRelRoLocal(StringRef, SMLoc) { 102 return ParseSectionSwitch(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS, 103 MCSectionELF::SHF_ALLOC | 104 MCSectionELF::SHF_WRITE, 105 SectionKind::getReadOnlyWithRelLocal()); 106 } 107 bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { 108 return ParseSectionSwitch(".eh_frame", MCSectionELF::SHT_PROGBITS, 109 MCSectionELF::SHF_ALLOC | 110 MCSectionELF::SHF_WRITE, 111 SectionKind::getDataRel()); 112 } 113 bool ParseDirectiveSection(StringRef, SMLoc); 114 bool ParseDirectiveSize(StringRef, SMLoc); 115 bool ParseDirectivePrevious(StringRef, SMLoc); 116 bool ParseDirectiveType(StringRef, SMLoc); 117 118private: 119 bool ParseSectionName(StringRef &SectionName); 120}; 121 122} 123 124bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, 125 unsigned Flags, SectionKind Kind) { 126 if (getLexer().isNot(AsmToken::EndOfStatement)) 127 return TokError("unexpected token in section switching directive"); 128 Lex(); 129 130 getStreamer().SwitchSection(getContext().getELFSection( 131 Section, Type, Flags, Kind)); 132 133 return false; 134} 135 136bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { 137 StringRef Name; 138 if (getParser().ParseIdentifier(Name)) 139 return TokError("expected identifier in directive"); 140 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);; 141 142 if (getLexer().isNot(AsmToken::Comma)) 143 return TokError("unexpected token in directive"); 144 Lex(); 145 146 const MCExpr *Expr; 147 if (getParser().ParseExpression(Expr)) 148 return true; 149 150 if (getLexer().isNot(AsmToken::EndOfStatement)) 151 return TokError("unexpected token in directive"); 152 153 getStreamer().EmitELFSize(Sym, Expr); 154 return false; 155} 156 157bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { 158 // A section name can contain -, so we cannot just use 159 // ParseIdentifier. 160 SMLoc FirstLoc = getLexer().getLoc(); 161 unsigned Size = 0; 162 163 for (;;) { 164 StringRef Tmp; 165 unsigned CurSize; 166 167 SMLoc PrevLoc = getLexer().getLoc(); 168 if (getLexer().is(AsmToken::Minus)) { 169 CurSize = 1; 170 Lex(); // Consume the "-". 171 } else if (!getParser().ParseIdentifier(Tmp)) 172 CurSize = Tmp.size(); 173 else 174 break; 175 176 Size += CurSize; 177 SectionName = StringRef(FirstLoc.getPointer(), Size); 178 179 // Make sure the following token is adjacent. 180 if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) 181 break; 182 } 183 if (Size == 0) 184 return true; 185 186 return false; 187} 188 189// FIXME: This is a work in progress. 190bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 191 StringRef SectionName; 192 193 if (ParseSectionName(SectionName)) 194 return TokError("expected identifier in directive"); 195 196 std::string FlagsStr; 197 StringRef TypeName; 198 int64_t Size = 0; 199 if (getLexer().is(AsmToken::Comma)) { 200 Lex(); 201 202 if (getLexer().isNot(AsmToken::String)) 203 return TokError("expected string in directive"); 204 205 FlagsStr = getTok().getStringContents(); 206 Lex(); 207 208 AsmToken::TokenKind TypeStartToken; 209 if (getContext().getAsmInfo().getCommentString()[0] == '@') 210 TypeStartToken = AsmToken::Percent; 211 else 212 TypeStartToken = AsmToken::At; 213 214 if (getLexer().is(AsmToken::Comma)) { 215 Lex(); 216 if (getLexer().is(TypeStartToken)) { 217 Lex(); 218 if (getParser().ParseIdentifier(TypeName)) 219 return TokError("expected identifier in directive"); 220 221 if (getLexer().is(AsmToken::Comma)) { 222 Lex(); 223 224 if (getParser().ParseAbsoluteExpression(Size)) 225 return true; 226 227 if (Size <= 0) 228 return TokError("section size must be positive"); 229 } 230 } 231 } 232 } 233 234 if (getLexer().isNot(AsmToken::EndOfStatement)) 235 return TokError("unexpected token in directive"); 236 237 unsigned Flags = 0; 238 for (unsigned i = 0; i < FlagsStr.size(); i++) { 239 switch (FlagsStr[i]) { 240 case 'a': 241 Flags |= MCSectionELF::SHF_ALLOC; 242 break; 243 case 'x': 244 Flags |= MCSectionELF::SHF_EXECINSTR; 245 break; 246 case 'w': 247 Flags |= MCSectionELF::SHF_WRITE; 248 break; 249 case 'M': 250 Flags |= MCSectionELF::SHF_MERGE; 251 break; 252 case 'S': 253 Flags |= MCSectionELF::SHF_STRINGS; 254 break; 255 case 'T': 256 Flags |= MCSectionELF::SHF_TLS; 257 break; 258 case 'c': 259 Flags |= MCSectionELF::XCORE_SHF_CP_SECTION; 260 break; 261 case 'd': 262 Flags |= MCSectionELF::XCORE_SHF_DP_SECTION; 263 break; 264 default: 265 return TokError("unknown flag"); 266 } 267 } 268 269 unsigned Type = MCSectionELF::SHT_NULL; 270 if (!TypeName.empty()) { 271 if (TypeName == "init_array") 272 Type = MCSectionELF::SHT_INIT_ARRAY; 273 else if (TypeName == "fini_array") 274 Type = MCSectionELF::SHT_FINI_ARRAY; 275 else if (TypeName == "preinit_array") 276 Type = MCSectionELF::SHT_PREINIT_ARRAY; 277 else if (TypeName == "nobits") 278 Type = MCSectionELF::SHT_NOBITS; 279 else if (TypeName == "progbits") 280 Type = MCSectionELF::SHT_PROGBITS; 281 else 282 return TokError("unknown section type"); 283 } 284 285 SectionKind Kind = (Flags & MCSectionELF::SHF_EXECINSTR) 286 ? SectionKind::getText() 287 : SectionKind::getDataRel(); 288 getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, 289 Flags, Kind, false, 290 Size)); 291 return false; 292} 293 294bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { 295 const MCSection *PreviousSection = getStreamer().getPreviousSection(); 296 if (PreviousSection != NULL) 297 getStreamer().SwitchSection(PreviousSection); 298 299 return false; 300} 301 302/// ParseDirectiveELFType 303/// ::= .type identifier , @attribute 304bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 305 StringRef Name; 306 if (getParser().ParseIdentifier(Name)) 307 return TokError("expected identifier in directive"); 308 309 // Handle the identifier as the key symbol. 310 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 311 312 if (getLexer().isNot(AsmToken::Comma)) 313 return TokError("unexpected token in '.type' directive"); 314 Lex(); 315 316 if (getLexer().isNot(AsmToken::At)) 317 return TokError("expected '@' before type"); 318 Lex(); 319 320 StringRef Type; 321 SMLoc TypeLoc; 322 323 TypeLoc = getLexer().getLoc(); 324 if (getParser().ParseIdentifier(Type)) 325 return TokError("expected symbol type in directive"); 326 327 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type) 328 .Case("function", MCSA_ELF_TypeFunction) 329 .Case("object", MCSA_ELF_TypeObject) 330 .Case("tls_object", MCSA_ELF_TypeTLS) 331 .Case("common", MCSA_ELF_TypeCommon) 332 .Case("notype", MCSA_ELF_TypeNoType) 333 .Default(MCSA_Invalid); 334 335 if (Attr == MCSA_Invalid) 336 return Error(TypeLoc, "unsupported attribute in '.type' directive"); 337 338 if (getLexer().isNot(AsmToken::EndOfStatement)) 339 return TokError("unexpected token in '.type' directive"); 340 341 Lex(); 342 343 getStreamer().EmitSymbolAttribute(Sym, Attr); 344 345 return false; 346} 347 348namespace llvm { 349 350MCAsmParserExtension *createELFAsmParser() { 351 return new ELFAsmParser; 352} 353 354} 355