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