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