1*9880d681SAndroid Build Coastguard Worker //===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmParserExtension.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmLexer.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionELF.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbolELF.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ELF.h"
21*9880d681SAndroid Build Coastguard Worker using namespace llvm;
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker namespace {
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker class ELFAsmParser : public MCAsmParserExtension {
26*9880d681SAndroid Build Coastguard Worker template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
addDirectiveHandler(StringRef Directive)27*9880d681SAndroid Build Coastguard Worker void addDirectiveHandler(StringRef Directive) {
28*9880d681SAndroid Build Coastguard Worker MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
29*9880d681SAndroid Build Coastguard Worker this, HandleDirective<ELFAsmParser, HandlerMethod>);
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker getParser().addDirectiveHandler(Directive, Handler);
32*9880d681SAndroid Build Coastguard Worker }
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
35*9880d681SAndroid Build Coastguard Worker SectionKind Kind);
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker public:
ELFAsmParser()38*9880d681SAndroid Build Coastguard Worker ELFAsmParser() { BracketExpressionsSupported = true; }
39*9880d681SAndroid Build Coastguard Worker
Initialize(MCAsmParser & Parser)40*9880d681SAndroid Build Coastguard Worker void Initialize(MCAsmParser &Parser) override {
41*9880d681SAndroid Build Coastguard Worker // Call the base implementation.
42*9880d681SAndroid Build Coastguard Worker this->MCAsmParserExtension::Initialize(Parser);
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
45*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
46*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
47*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
48*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
49*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
50*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<
51*9880d681SAndroid Build Coastguard Worker &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
52*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<
53*9880d681SAndroid Build Coastguard Worker &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
54*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<
55*9880d681SAndroid Build Coastguard Worker &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
56*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
57*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<
58*9880d681SAndroid Build Coastguard Worker &ELFAsmParser::ParseDirectivePushSection>(".pushsection");
59*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
60*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
61*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
62*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
63*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
64*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
65*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");
66*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
67*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
68*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
69*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<
70*9880d681SAndroid Build Coastguard Worker &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
71*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<
72*9880d681SAndroid Build Coastguard Worker &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
73*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<
74*9880d681SAndroid Build Coastguard Worker &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
75*9880d681SAndroid Build Coastguard Worker addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
76*9880d681SAndroid Build Coastguard Worker }
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
79*9880d681SAndroid Build Coastguard Worker // the best way for us to get access to it?
ParseSectionDirectiveData(StringRef,SMLoc)80*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveData(StringRef, SMLoc) {
81*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
82*9880d681SAndroid Build Coastguard Worker ELF::SHF_WRITE | ELF::SHF_ALLOC,
83*9880d681SAndroid Build Coastguard Worker SectionKind::getData());
84*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveText(StringRef,SMLoc)85*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveText(StringRef, SMLoc) {
86*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
87*9880d681SAndroid Build Coastguard Worker ELF::SHF_EXECINSTR |
88*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC, SectionKind::getText());
89*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveBSS(StringRef,SMLoc)90*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
91*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
92*9880d681SAndroid Build Coastguard Worker ELF::SHF_WRITE |
93*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC, SectionKind::getBSS());
94*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveRoData(StringRef,SMLoc)95*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
96*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
97*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC,
98*9880d681SAndroid Build Coastguard Worker SectionKind::getReadOnly());
99*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveTData(StringRef,SMLoc)100*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveTData(StringRef, SMLoc) {
101*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
102*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC |
103*9880d681SAndroid Build Coastguard Worker ELF::SHF_TLS | ELF::SHF_WRITE,
104*9880d681SAndroid Build Coastguard Worker SectionKind::getThreadData());
105*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveTBSS(StringRef,SMLoc)106*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
107*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
108*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC |
109*9880d681SAndroid Build Coastguard Worker ELF::SHF_TLS | ELF::SHF_WRITE,
110*9880d681SAndroid Build Coastguard Worker SectionKind::getThreadBSS());
111*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveDataRel(StringRef,SMLoc)112*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
113*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
114*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC | ELF::SHF_WRITE,
115*9880d681SAndroid Build Coastguard Worker SectionKind::getData());
116*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveDataRelRo(StringRef,SMLoc)117*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
118*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
119*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC |
120*9880d681SAndroid Build Coastguard Worker ELF::SHF_WRITE,
121*9880d681SAndroid Build Coastguard Worker SectionKind::getReadOnlyWithRel());
122*9880d681SAndroid Build Coastguard Worker }
ParseSectionDirectiveEhFrame(StringRef,SMLoc)123*9880d681SAndroid Build Coastguard Worker bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
124*9880d681SAndroid Build Coastguard Worker return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
125*9880d681SAndroid Build Coastguard Worker ELF::SHF_ALLOC | ELF::SHF_WRITE,
126*9880d681SAndroid Build Coastguard Worker SectionKind::getData());
127*9880d681SAndroid Build Coastguard Worker }
128*9880d681SAndroid Build Coastguard Worker bool ParseDirectivePushSection(StringRef, SMLoc);
129*9880d681SAndroid Build Coastguard Worker bool ParseDirectivePopSection(StringRef, SMLoc);
130*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveSection(StringRef, SMLoc);
131*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveSize(StringRef, SMLoc);
132*9880d681SAndroid Build Coastguard Worker bool ParseDirectivePrevious(StringRef, SMLoc);
133*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveType(StringRef, SMLoc);
134*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveIdent(StringRef, SMLoc);
135*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveSymver(StringRef, SMLoc);
136*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveVersion(StringRef, SMLoc);
137*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveWeakref(StringRef, SMLoc);
138*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
139*9880d681SAndroid Build Coastguard Worker bool ParseDirectiveSubsection(StringRef, SMLoc);
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker private:
142*9880d681SAndroid Build Coastguard Worker bool ParseSectionName(StringRef &SectionName);
143*9880d681SAndroid Build Coastguard Worker bool ParseSectionArguments(bool IsPush, SMLoc loc);
144*9880d681SAndroid Build Coastguard Worker unsigned parseSunStyleSectionFlags();
145*9880d681SAndroid Build Coastguard Worker };
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveSymbolAttribute
150*9880d681SAndroid Build Coastguard Worker /// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
ParseDirectiveSymbolAttribute(StringRef Directive,SMLoc)151*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
152*9880d681SAndroid Build Coastguard Worker MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
153*9880d681SAndroid Build Coastguard Worker .Case(".weak", MCSA_Weak)
154*9880d681SAndroid Build Coastguard Worker .Case(".local", MCSA_Local)
155*9880d681SAndroid Build Coastguard Worker .Case(".hidden", MCSA_Hidden)
156*9880d681SAndroid Build Coastguard Worker .Case(".internal", MCSA_Internal)
157*9880d681SAndroid Build Coastguard Worker .Case(".protected", MCSA_Protected)
158*9880d681SAndroid Build Coastguard Worker .Default(MCSA_Invalid);
159*9880d681SAndroid Build Coastguard Worker assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
160*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
161*9880d681SAndroid Build Coastguard Worker for (;;) {
162*9880d681SAndroid Build Coastguard Worker StringRef Name;
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(Name))
165*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Worker getStreamer().EmitSymbolAttribute(Sym, Attr);
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::EndOfStatement))
172*9880d681SAndroid Build Coastguard Worker break;
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
175*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in directive");
176*9880d681SAndroid Build Coastguard Worker Lex();
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker Lex();
181*9880d681SAndroid Build Coastguard Worker return false;
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker
ParseSectionSwitch(StringRef Section,unsigned Type,unsigned Flags,SectionKind Kind)184*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
185*9880d681SAndroid Build Coastguard Worker unsigned Flags, SectionKind Kind) {
186*9880d681SAndroid Build Coastguard Worker const MCExpr *Subsection = nullptr;
187*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
188*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Subsection))
189*9880d681SAndroid Build Coastguard Worker return true;
190*9880d681SAndroid Build Coastguard Worker }
191*9880d681SAndroid Build Coastguard Worker Lex();
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags),
194*9880d681SAndroid Build Coastguard Worker Subsection);
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker return false;
197*9880d681SAndroid Build Coastguard Worker }
198*9880d681SAndroid Build Coastguard Worker
ParseDirectiveSize(StringRef,SMLoc)199*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
200*9880d681SAndroid Build Coastguard Worker StringRef Name;
201*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(Name))
202*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
203*9880d681SAndroid Build Coastguard Worker MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
206*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in directive");
207*9880d681SAndroid Build Coastguard Worker Lex();
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr;
210*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Expr))
211*9880d681SAndroid Build Coastguard Worker return true;
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement))
214*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in directive");
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard Worker getStreamer().emitELFSize(Sym, Expr);
217*9880d681SAndroid Build Coastguard Worker return false;
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker
ParseSectionName(StringRef & SectionName)220*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
221*9880d681SAndroid Build Coastguard Worker // A section name can contain -, so we cannot just use
222*9880d681SAndroid Build Coastguard Worker // parseIdentifier.
223*9880d681SAndroid Build Coastguard Worker SMLoc FirstLoc = getLexer().getLoc();
224*9880d681SAndroid Build Coastguard Worker unsigned Size = 0;
225*9880d681SAndroid Build Coastguard Worker
226*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::String)) {
227*9880d681SAndroid Build Coastguard Worker SectionName = getTok().getIdentifier();
228*9880d681SAndroid Build Coastguard Worker Lex();
229*9880d681SAndroid Build Coastguard Worker return false;
230*9880d681SAndroid Build Coastguard Worker }
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker for (;;) {
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker SMLoc PrevLoc = getLexer().getLoc();
235*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::Comma) ||
236*9880d681SAndroid Build Coastguard Worker getLexer().is(AsmToken::EndOfStatement))
237*9880d681SAndroid Build Coastguard Worker break;
238*9880d681SAndroid Build Coastguard Worker
239*9880d681SAndroid Build Coastguard Worker unsigned CurSize;
240*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::String)) {
241*9880d681SAndroid Build Coastguard Worker CurSize = getTok().getIdentifier().size() + 2;
242*9880d681SAndroid Build Coastguard Worker Lex();
243*9880d681SAndroid Build Coastguard Worker } else if (getLexer().is(AsmToken::Identifier)) {
244*9880d681SAndroid Build Coastguard Worker CurSize = getTok().getIdentifier().size();
245*9880d681SAndroid Build Coastguard Worker Lex();
246*9880d681SAndroid Build Coastguard Worker } else {
247*9880d681SAndroid Build Coastguard Worker CurSize = getTok().getString().size();
248*9880d681SAndroid Build Coastguard Worker Lex();
249*9880d681SAndroid Build Coastguard Worker }
250*9880d681SAndroid Build Coastguard Worker Size += CurSize;
251*9880d681SAndroid Build Coastguard Worker SectionName = StringRef(FirstLoc.getPointer(), Size);
252*9880d681SAndroid Build Coastguard Worker
253*9880d681SAndroid Build Coastguard Worker // Make sure the following token is adjacent.
254*9880d681SAndroid Build Coastguard Worker if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
255*9880d681SAndroid Build Coastguard Worker break;
256*9880d681SAndroid Build Coastguard Worker }
257*9880d681SAndroid Build Coastguard Worker if (Size == 0)
258*9880d681SAndroid Build Coastguard Worker return true;
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker return false;
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker
parseSectionFlags(StringRef flagsStr,bool * UseLastGroup)263*9880d681SAndroid Build Coastguard Worker static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
264*9880d681SAndroid Build Coastguard Worker unsigned flags = 0;
265*9880d681SAndroid Build Coastguard Worker
266*9880d681SAndroid Build Coastguard Worker for (char i : flagsStr) {
267*9880d681SAndroid Build Coastguard Worker switch (i) {
268*9880d681SAndroid Build Coastguard Worker case 'a':
269*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_ALLOC;
270*9880d681SAndroid Build Coastguard Worker break;
271*9880d681SAndroid Build Coastguard Worker case 'e':
272*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_EXCLUDE;
273*9880d681SAndroid Build Coastguard Worker break;
274*9880d681SAndroid Build Coastguard Worker case 'x':
275*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_EXECINSTR;
276*9880d681SAndroid Build Coastguard Worker break;
277*9880d681SAndroid Build Coastguard Worker case 'w':
278*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_WRITE;
279*9880d681SAndroid Build Coastguard Worker break;
280*9880d681SAndroid Build Coastguard Worker case 'M':
281*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_MERGE;
282*9880d681SAndroid Build Coastguard Worker break;
283*9880d681SAndroid Build Coastguard Worker case 'S':
284*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_STRINGS;
285*9880d681SAndroid Build Coastguard Worker break;
286*9880d681SAndroid Build Coastguard Worker case 'T':
287*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_TLS;
288*9880d681SAndroid Build Coastguard Worker break;
289*9880d681SAndroid Build Coastguard Worker case 'c':
290*9880d681SAndroid Build Coastguard Worker flags |= ELF::XCORE_SHF_CP_SECTION;
291*9880d681SAndroid Build Coastguard Worker break;
292*9880d681SAndroid Build Coastguard Worker case 'd':
293*9880d681SAndroid Build Coastguard Worker flags |= ELF::XCORE_SHF_DP_SECTION;
294*9880d681SAndroid Build Coastguard Worker break;
295*9880d681SAndroid Build Coastguard Worker case 'G':
296*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_GROUP;
297*9880d681SAndroid Build Coastguard Worker break;
298*9880d681SAndroid Build Coastguard Worker case '?':
299*9880d681SAndroid Build Coastguard Worker *UseLastGroup = true;
300*9880d681SAndroid Build Coastguard Worker break;
301*9880d681SAndroid Build Coastguard Worker default:
302*9880d681SAndroid Build Coastguard Worker return -1U;
303*9880d681SAndroid Build Coastguard Worker }
304*9880d681SAndroid Build Coastguard Worker }
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker return flags;
307*9880d681SAndroid Build Coastguard Worker }
308*9880d681SAndroid Build Coastguard Worker
parseSunStyleSectionFlags()309*9880d681SAndroid Build Coastguard Worker unsigned ELFAsmParser::parseSunStyleSectionFlags() {
310*9880d681SAndroid Build Coastguard Worker unsigned flags = 0;
311*9880d681SAndroid Build Coastguard Worker while (getLexer().is(AsmToken::Hash)) {
312*9880d681SAndroid Build Coastguard Worker Lex(); // Eat the #.
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker if (!getLexer().is(AsmToken::Identifier))
315*9880d681SAndroid Build Coastguard Worker return -1U;
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker StringRef flagId = getTok().getIdentifier();
318*9880d681SAndroid Build Coastguard Worker if (flagId == "alloc")
319*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_ALLOC;
320*9880d681SAndroid Build Coastguard Worker else if (flagId == "execinstr")
321*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_EXECINSTR;
322*9880d681SAndroid Build Coastguard Worker else if (flagId == "write")
323*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_WRITE;
324*9880d681SAndroid Build Coastguard Worker else if (flagId == "tls")
325*9880d681SAndroid Build Coastguard Worker flags |= ELF::SHF_TLS;
326*9880d681SAndroid Build Coastguard Worker else
327*9880d681SAndroid Build Coastguard Worker return -1U;
328*9880d681SAndroid Build Coastguard Worker
329*9880d681SAndroid Build Coastguard Worker Lex(); // Eat the flag.
330*9880d681SAndroid Build Coastguard Worker
331*9880d681SAndroid Build Coastguard Worker if (!getLexer().is(AsmToken::Comma))
332*9880d681SAndroid Build Coastguard Worker break;
333*9880d681SAndroid Build Coastguard Worker Lex(); // Eat the comma.
334*9880d681SAndroid Build Coastguard Worker }
335*9880d681SAndroid Build Coastguard Worker return flags;
336*9880d681SAndroid Build Coastguard Worker }
337*9880d681SAndroid Build Coastguard Worker
338*9880d681SAndroid Build Coastguard Worker
ParseDirectivePushSection(StringRef s,SMLoc loc)339*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
340*9880d681SAndroid Build Coastguard Worker getStreamer().PushSection();
341*9880d681SAndroid Build Coastguard Worker
342*9880d681SAndroid Build Coastguard Worker if (ParseSectionArguments(/*IsPush=*/true, loc)) {
343*9880d681SAndroid Build Coastguard Worker getStreamer().PopSection();
344*9880d681SAndroid Build Coastguard Worker return true;
345*9880d681SAndroid Build Coastguard Worker }
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Worker return false;
348*9880d681SAndroid Build Coastguard Worker }
349*9880d681SAndroid Build Coastguard Worker
ParseDirectivePopSection(StringRef,SMLoc)350*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
351*9880d681SAndroid Build Coastguard Worker if (!getStreamer().PopSection())
352*9880d681SAndroid Build Coastguard Worker return TokError(".popsection without corresponding .pushsection");
353*9880d681SAndroid Build Coastguard Worker return false;
354*9880d681SAndroid Build Coastguard Worker }
355*9880d681SAndroid Build Coastguard Worker
356*9880d681SAndroid Build Coastguard Worker // FIXME: This is a work in progress.
ParseDirectiveSection(StringRef,SMLoc loc)357*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
358*9880d681SAndroid Build Coastguard Worker return ParseSectionArguments(/*IsPush=*/false, loc);
359*9880d681SAndroid Build Coastguard Worker }
360*9880d681SAndroid Build Coastguard Worker
ParseSectionArguments(bool IsPush,SMLoc loc)361*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
362*9880d681SAndroid Build Coastguard Worker StringRef SectionName;
363*9880d681SAndroid Build Coastguard Worker
364*9880d681SAndroid Build Coastguard Worker if (ParseSectionName(SectionName))
365*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
366*9880d681SAndroid Build Coastguard Worker
367*9880d681SAndroid Build Coastguard Worker StringRef TypeName;
368*9880d681SAndroid Build Coastguard Worker int64_t Size = 0;
369*9880d681SAndroid Build Coastguard Worker StringRef GroupName;
370*9880d681SAndroid Build Coastguard Worker unsigned Flags = 0;
371*9880d681SAndroid Build Coastguard Worker const MCExpr *Subsection = nullptr;
372*9880d681SAndroid Build Coastguard Worker bool UseLastGroup = false;
373*9880d681SAndroid Build Coastguard Worker StringRef UniqueStr;
374*9880d681SAndroid Build Coastguard Worker int64_t UniqueID = ~0;
375*9880d681SAndroid Build Coastguard Worker
376*9880d681SAndroid Build Coastguard Worker // Set the defaults first.
377*9880d681SAndroid Build Coastguard Worker if (SectionName == ".fini" || SectionName == ".init" ||
378*9880d681SAndroid Build Coastguard Worker SectionName == ".rodata")
379*9880d681SAndroid Build Coastguard Worker Flags |= ELF::SHF_ALLOC;
380*9880d681SAndroid Build Coastguard Worker if (SectionName == ".fini" || SectionName == ".init")
381*9880d681SAndroid Build Coastguard Worker Flags |= ELF::SHF_EXECINSTR;
382*9880d681SAndroid Build Coastguard Worker
383*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::Comma)) {
384*9880d681SAndroid Build Coastguard Worker Lex();
385*9880d681SAndroid Build Coastguard Worker
386*9880d681SAndroid Build Coastguard Worker if (IsPush && getLexer().isNot(AsmToken::String)) {
387*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Subsection))
388*9880d681SAndroid Build Coastguard Worker return true;
389*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
390*9880d681SAndroid Build Coastguard Worker goto EndStmt;
391*9880d681SAndroid Build Coastguard Worker Lex();
392*9880d681SAndroid Build Coastguard Worker }
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker unsigned extraFlags;
395*9880d681SAndroid Build Coastguard Worker
396*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::String)) {
397*9880d681SAndroid Build Coastguard Worker if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
398*9880d681SAndroid Build Coastguard Worker || getLexer().isNot(AsmToken::Hash))
399*9880d681SAndroid Build Coastguard Worker return TokError("expected string in directive");
400*9880d681SAndroid Build Coastguard Worker extraFlags = parseSunStyleSectionFlags();
401*9880d681SAndroid Build Coastguard Worker } else {
402*9880d681SAndroid Build Coastguard Worker StringRef FlagsStr = getTok().getStringContents();
403*9880d681SAndroid Build Coastguard Worker Lex();
404*9880d681SAndroid Build Coastguard Worker extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
405*9880d681SAndroid Build Coastguard Worker }
406*9880d681SAndroid Build Coastguard Worker
407*9880d681SAndroid Build Coastguard Worker if (extraFlags == -1U)
408*9880d681SAndroid Build Coastguard Worker return TokError("unknown flag");
409*9880d681SAndroid Build Coastguard Worker Flags |= extraFlags;
410*9880d681SAndroid Build Coastguard Worker
411*9880d681SAndroid Build Coastguard Worker bool Mergeable = Flags & ELF::SHF_MERGE;
412*9880d681SAndroid Build Coastguard Worker bool Group = Flags & ELF::SHF_GROUP;
413*9880d681SAndroid Build Coastguard Worker if (Group && UseLastGroup)
414*9880d681SAndroid Build Coastguard Worker return TokError("Section cannot specifiy a group name while also acting "
415*9880d681SAndroid Build Coastguard Worker "as a member of the last group");
416*9880d681SAndroid Build Coastguard Worker
417*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma)) {
418*9880d681SAndroid Build Coastguard Worker if (Mergeable)
419*9880d681SAndroid Build Coastguard Worker return TokError("Mergeable section must specify the type");
420*9880d681SAndroid Build Coastguard Worker if (Group)
421*9880d681SAndroid Build Coastguard Worker return TokError("Group section must specify the type");
422*9880d681SAndroid Build Coastguard Worker } else {
423*9880d681SAndroid Build Coastguard Worker Lex();
424*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::At) || getLexer().is(AsmToken::Percent) ||
425*9880d681SAndroid Build Coastguard Worker getLexer().is(AsmToken::String)) {
426*9880d681SAndroid Build Coastguard Worker if (!getLexer().is(AsmToken::String))
427*9880d681SAndroid Build Coastguard Worker Lex();
428*9880d681SAndroid Build Coastguard Worker } else
429*9880d681SAndroid Build Coastguard Worker return TokError("expected '@<type>', '%<type>' or \"<type>\"");
430*9880d681SAndroid Build Coastguard Worker
431*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(TypeName))
432*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
433*9880d681SAndroid Build Coastguard Worker
434*9880d681SAndroid Build Coastguard Worker if (Mergeable) {
435*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
436*9880d681SAndroid Build Coastguard Worker return TokError("expected the entry size");
437*9880d681SAndroid Build Coastguard Worker Lex();
438*9880d681SAndroid Build Coastguard Worker if (getParser().parseAbsoluteExpression(Size))
439*9880d681SAndroid Build Coastguard Worker return true;
440*9880d681SAndroid Build Coastguard Worker if (Size <= 0)
441*9880d681SAndroid Build Coastguard Worker return TokError("entry size must be positive");
442*9880d681SAndroid Build Coastguard Worker }
443*9880d681SAndroid Build Coastguard Worker
444*9880d681SAndroid Build Coastguard Worker if (Group) {
445*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
446*9880d681SAndroid Build Coastguard Worker return TokError("expected group name");
447*9880d681SAndroid Build Coastguard Worker Lex();
448*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(GroupName))
449*9880d681SAndroid Build Coastguard Worker return true;
450*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::Comma)) {
451*9880d681SAndroid Build Coastguard Worker Lex();
452*9880d681SAndroid Build Coastguard Worker StringRef Linkage;
453*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(Linkage))
454*9880d681SAndroid Build Coastguard Worker return true;
455*9880d681SAndroid Build Coastguard Worker if (Linkage != "comdat")
456*9880d681SAndroid Build Coastguard Worker return TokError("Linkage must be 'comdat'");
457*9880d681SAndroid Build Coastguard Worker }
458*9880d681SAndroid Build Coastguard Worker }
459*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::Comma)) {
460*9880d681SAndroid Build Coastguard Worker Lex();
461*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(UniqueStr))
462*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
463*9880d681SAndroid Build Coastguard Worker if (UniqueStr != "unique")
464*9880d681SAndroid Build Coastguard Worker return TokError("expected 'unique'");
465*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
466*9880d681SAndroid Build Coastguard Worker return TokError("expected commma");
467*9880d681SAndroid Build Coastguard Worker Lex();
468*9880d681SAndroid Build Coastguard Worker if (getParser().parseAbsoluteExpression(UniqueID))
469*9880d681SAndroid Build Coastguard Worker return true;
470*9880d681SAndroid Build Coastguard Worker if (UniqueID < 0)
471*9880d681SAndroid Build Coastguard Worker return TokError("unique id must be positive");
472*9880d681SAndroid Build Coastguard Worker if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
473*9880d681SAndroid Build Coastguard Worker return TokError("unique id is too large");
474*9880d681SAndroid Build Coastguard Worker }
475*9880d681SAndroid Build Coastguard Worker }
476*9880d681SAndroid Build Coastguard Worker }
477*9880d681SAndroid Build Coastguard Worker
478*9880d681SAndroid Build Coastguard Worker EndStmt:
479*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement))
480*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in directive");
481*9880d681SAndroid Build Coastguard Worker
482*9880d681SAndroid Build Coastguard Worker unsigned Type = ELF::SHT_PROGBITS;
483*9880d681SAndroid Build Coastguard Worker
484*9880d681SAndroid Build Coastguard Worker if (TypeName.empty()) {
485*9880d681SAndroid Build Coastguard Worker if (SectionName.startswith(".note"))
486*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_NOTE;
487*9880d681SAndroid Build Coastguard Worker else if (SectionName == ".init_array")
488*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_INIT_ARRAY;
489*9880d681SAndroid Build Coastguard Worker else if (SectionName == ".fini_array")
490*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_FINI_ARRAY;
491*9880d681SAndroid Build Coastguard Worker else if (SectionName == ".preinit_array")
492*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_PREINIT_ARRAY;
493*9880d681SAndroid Build Coastguard Worker } else {
494*9880d681SAndroid Build Coastguard Worker if (TypeName == "init_array")
495*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_INIT_ARRAY;
496*9880d681SAndroid Build Coastguard Worker else if (TypeName == "fini_array")
497*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_FINI_ARRAY;
498*9880d681SAndroid Build Coastguard Worker else if (TypeName == "preinit_array")
499*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_PREINIT_ARRAY;
500*9880d681SAndroid Build Coastguard Worker else if (TypeName == "nobits")
501*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_NOBITS;
502*9880d681SAndroid Build Coastguard Worker else if (TypeName == "progbits")
503*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_PROGBITS;
504*9880d681SAndroid Build Coastguard Worker else if (TypeName == "note")
505*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_NOTE;
506*9880d681SAndroid Build Coastguard Worker else if (TypeName == "unwind")
507*9880d681SAndroid Build Coastguard Worker Type = ELF::SHT_X86_64_UNWIND;
508*9880d681SAndroid Build Coastguard Worker else
509*9880d681SAndroid Build Coastguard Worker return TokError("unknown section type");
510*9880d681SAndroid Build Coastguard Worker }
511*9880d681SAndroid Build Coastguard Worker
512*9880d681SAndroid Build Coastguard Worker if (UseLastGroup) {
513*9880d681SAndroid Build Coastguard Worker MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
514*9880d681SAndroid Build Coastguard Worker if (const MCSectionELF *Section =
515*9880d681SAndroid Build Coastguard Worker cast_or_null<MCSectionELF>(CurrentSection.first))
516*9880d681SAndroid Build Coastguard Worker if (const MCSymbol *Group = Section->getGroup()) {
517*9880d681SAndroid Build Coastguard Worker GroupName = Group->getName();
518*9880d681SAndroid Build Coastguard Worker Flags |= ELF::SHF_GROUP;
519*9880d681SAndroid Build Coastguard Worker }
520*9880d681SAndroid Build Coastguard Worker }
521*9880d681SAndroid Build Coastguard Worker
522*9880d681SAndroid Build Coastguard Worker MCSection *ELFSection = getContext().getELFSection(SectionName, Type, Flags,
523*9880d681SAndroid Build Coastguard Worker Size, GroupName, UniqueID);
524*9880d681SAndroid Build Coastguard Worker getStreamer().SwitchSection(ELFSection, Subsection);
525*9880d681SAndroid Build Coastguard Worker
526*9880d681SAndroid Build Coastguard Worker if (getContext().getGenDwarfForAssembly()) {
527*9880d681SAndroid Build Coastguard Worker bool InsertResult = getContext().addGenDwarfSection(ELFSection);
528*9880d681SAndroid Build Coastguard Worker if (InsertResult) {
529*9880d681SAndroid Build Coastguard Worker if (getContext().getDwarfVersion() <= 2)
530*9880d681SAndroid Build Coastguard Worker Warning(loc, "DWARF2 only supports one section per compilation unit");
531*9880d681SAndroid Build Coastguard Worker
532*9880d681SAndroid Build Coastguard Worker if (!ELFSection->getBeginSymbol()) {
533*9880d681SAndroid Build Coastguard Worker MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
534*9880d681SAndroid Build Coastguard Worker getStreamer().EmitLabel(SectionStartSymbol);
535*9880d681SAndroid Build Coastguard Worker ELFSection->setBeginSymbol(SectionStartSymbol);
536*9880d681SAndroid Build Coastguard Worker }
537*9880d681SAndroid Build Coastguard Worker }
538*9880d681SAndroid Build Coastguard Worker }
539*9880d681SAndroid Build Coastguard Worker
540*9880d681SAndroid Build Coastguard Worker return false;
541*9880d681SAndroid Build Coastguard Worker }
542*9880d681SAndroid Build Coastguard Worker
ParseDirectivePrevious(StringRef DirName,SMLoc)543*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
544*9880d681SAndroid Build Coastguard Worker MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
545*9880d681SAndroid Build Coastguard Worker if (PreviousSection.first == nullptr)
546*9880d681SAndroid Build Coastguard Worker return TokError(".previous without corresponding .section");
547*9880d681SAndroid Build Coastguard Worker getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
548*9880d681SAndroid Build Coastguard Worker
549*9880d681SAndroid Build Coastguard Worker return false;
550*9880d681SAndroid Build Coastguard Worker }
551*9880d681SAndroid Build Coastguard Worker
MCAttrForString(StringRef Type)552*9880d681SAndroid Build Coastguard Worker static MCSymbolAttr MCAttrForString(StringRef Type) {
553*9880d681SAndroid Build Coastguard Worker return StringSwitch<MCSymbolAttr>(Type)
554*9880d681SAndroid Build Coastguard Worker .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
555*9880d681SAndroid Build Coastguard Worker .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
556*9880d681SAndroid Build Coastguard Worker .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
557*9880d681SAndroid Build Coastguard Worker .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
558*9880d681SAndroid Build Coastguard Worker .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
559*9880d681SAndroid Build Coastguard Worker .Cases("STT_GNU_IFUNC", "gnu_indirect_function",
560*9880d681SAndroid Build Coastguard Worker MCSA_ELF_TypeIndFunction)
561*9880d681SAndroid Build Coastguard Worker .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
562*9880d681SAndroid Build Coastguard Worker .Default(MCSA_Invalid);
563*9880d681SAndroid Build Coastguard Worker }
564*9880d681SAndroid Build Coastguard Worker
565*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveELFType
566*9880d681SAndroid Build Coastguard Worker /// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
567*9880d681SAndroid Build Coastguard Worker /// ::= .type identifier , #attribute
568*9880d681SAndroid Build Coastguard Worker /// ::= .type identifier , @attribute
569*9880d681SAndroid Build Coastguard Worker /// ::= .type identifier , %attribute
570*9880d681SAndroid Build Coastguard Worker /// ::= .type identifier , "attribute"
ParseDirectiveType(StringRef,SMLoc)571*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
572*9880d681SAndroid Build Coastguard Worker StringRef Name;
573*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(Name))
574*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
575*9880d681SAndroid Build Coastguard Worker
576*9880d681SAndroid Build Coastguard Worker // Handle the identifier as the key symbol.
577*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
578*9880d681SAndroid Build Coastguard Worker
579*9880d681SAndroid Build Coastguard Worker // NOTE the comma is optional in all cases. It is only documented as being
580*9880d681SAndroid Build Coastguard Worker // optional in the first case, however, GAS will silently treat the comma as
581*9880d681SAndroid Build Coastguard Worker // optional in all cases. Furthermore, although the documentation states that
582*9880d681SAndroid Build Coastguard Worker // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
583*9880d681SAndroid Build Coastguard Worker // accepts both the upper case name as well as the lower case aliases.
584*9880d681SAndroid Build Coastguard Worker if (getLexer().is(AsmToken::Comma))
585*9880d681SAndroid Build Coastguard Worker Lex();
586*9880d681SAndroid Build Coastguard Worker
587*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Identifier) &&
588*9880d681SAndroid Build Coastguard Worker getLexer().isNot(AsmToken::Hash) &&
589*9880d681SAndroid Build Coastguard Worker getLexer().isNot(AsmToken::Percent) &&
590*9880d681SAndroid Build Coastguard Worker getLexer().isNot(AsmToken::String)) {
591*9880d681SAndroid Build Coastguard Worker if (!getLexer().getAllowAtInIdentifier())
592*9880d681SAndroid Build Coastguard Worker return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
593*9880d681SAndroid Build Coastguard Worker "'%<type>' or \"<type>\"");
594*9880d681SAndroid Build Coastguard Worker else if (getLexer().isNot(AsmToken::At))
595*9880d681SAndroid Build Coastguard Worker return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
596*9880d681SAndroid Build Coastguard Worker "'%<type>' or \"<type>\"");
597*9880d681SAndroid Build Coastguard Worker }
598*9880d681SAndroid Build Coastguard Worker
599*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::String) &&
600*9880d681SAndroid Build Coastguard Worker getLexer().isNot(AsmToken::Identifier))
601*9880d681SAndroid Build Coastguard Worker Lex();
602*9880d681SAndroid Build Coastguard Worker
603*9880d681SAndroid Build Coastguard Worker SMLoc TypeLoc = getLexer().getLoc();
604*9880d681SAndroid Build Coastguard Worker
605*9880d681SAndroid Build Coastguard Worker StringRef Type;
606*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(Type))
607*9880d681SAndroid Build Coastguard Worker return TokError("expected symbol type in directive");
608*9880d681SAndroid Build Coastguard Worker
609*9880d681SAndroid Build Coastguard Worker MCSymbolAttr Attr = MCAttrForString(Type);
610*9880d681SAndroid Build Coastguard Worker if (Attr == MCSA_Invalid)
611*9880d681SAndroid Build Coastguard Worker return Error(TypeLoc, "unsupported attribute in '.type' directive");
612*9880d681SAndroid Build Coastguard Worker
613*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement))
614*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in '.type' directive");
615*9880d681SAndroid Build Coastguard Worker Lex();
616*9880d681SAndroid Build Coastguard Worker
617*9880d681SAndroid Build Coastguard Worker getStreamer().EmitSymbolAttribute(Sym, Attr);
618*9880d681SAndroid Build Coastguard Worker
619*9880d681SAndroid Build Coastguard Worker return false;
620*9880d681SAndroid Build Coastguard Worker }
621*9880d681SAndroid Build Coastguard Worker
622*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveIdent
623*9880d681SAndroid Build Coastguard Worker /// ::= .ident string
ParseDirectiveIdent(StringRef,SMLoc)624*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
625*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::String))
626*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in '.ident' directive");
627*9880d681SAndroid Build Coastguard Worker
628*9880d681SAndroid Build Coastguard Worker StringRef Data = getTok().getIdentifier();
629*9880d681SAndroid Build Coastguard Worker
630*9880d681SAndroid Build Coastguard Worker Lex();
631*9880d681SAndroid Build Coastguard Worker
632*9880d681SAndroid Build Coastguard Worker getStreamer().EmitIdent(Data);
633*9880d681SAndroid Build Coastguard Worker return false;
634*9880d681SAndroid Build Coastguard Worker }
635*9880d681SAndroid Build Coastguard Worker
636*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveSymver
637*9880d681SAndroid Build Coastguard Worker /// ::= .symver foo, bar2@zed
ParseDirectiveSymver(StringRef,SMLoc)638*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
639*9880d681SAndroid Build Coastguard Worker StringRef Name;
640*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(Name))
641*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
642*9880d681SAndroid Build Coastguard Worker
643*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
644*9880d681SAndroid Build Coastguard Worker return TokError("expected a comma");
645*9880d681SAndroid Build Coastguard Worker
646*9880d681SAndroid Build Coastguard Worker // ARM assembly uses @ for a comment...
647*9880d681SAndroid Build Coastguard Worker // except when parsing the second parameter of the .symver directive.
648*9880d681SAndroid Build Coastguard Worker // Force the next symbol to allow @ in the identifier, which is
649*9880d681SAndroid Build Coastguard Worker // required for this directive and then reset it to its initial state.
650*9880d681SAndroid Build Coastguard Worker const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
651*9880d681SAndroid Build Coastguard Worker getLexer().setAllowAtInIdentifier(true);
652*9880d681SAndroid Build Coastguard Worker Lex();
653*9880d681SAndroid Build Coastguard Worker getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
654*9880d681SAndroid Build Coastguard Worker
655*9880d681SAndroid Build Coastguard Worker StringRef AliasName;
656*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(AliasName))
657*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
658*9880d681SAndroid Build Coastguard Worker
659*9880d681SAndroid Build Coastguard Worker if (AliasName.find('@') == StringRef::npos)
660*9880d681SAndroid Build Coastguard Worker return TokError("expected a '@' in the name");
661*9880d681SAndroid Build Coastguard Worker
662*9880d681SAndroid Build Coastguard Worker MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
663*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
664*9880d681SAndroid Build Coastguard Worker const MCExpr *Value = MCSymbolRefExpr::create(Sym, getContext());
665*9880d681SAndroid Build Coastguard Worker
666*9880d681SAndroid Build Coastguard Worker getStreamer().EmitAssignment(Alias, Value);
667*9880d681SAndroid Build Coastguard Worker return false;
668*9880d681SAndroid Build Coastguard Worker }
669*9880d681SAndroid Build Coastguard Worker
670*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveVersion
671*9880d681SAndroid Build Coastguard Worker /// ::= .version string
ParseDirectiveVersion(StringRef,SMLoc)672*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
673*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::String))
674*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in '.version' directive");
675*9880d681SAndroid Build Coastguard Worker
676*9880d681SAndroid Build Coastguard Worker StringRef Data = getTok().getIdentifier();
677*9880d681SAndroid Build Coastguard Worker
678*9880d681SAndroid Build Coastguard Worker Lex();
679*9880d681SAndroid Build Coastguard Worker
680*9880d681SAndroid Build Coastguard Worker MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
681*9880d681SAndroid Build Coastguard Worker
682*9880d681SAndroid Build Coastguard Worker getStreamer().PushSection();
683*9880d681SAndroid Build Coastguard Worker getStreamer().SwitchSection(Note);
684*9880d681SAndroid Build Coastguard Worker getStreamer().EmitIntValue(Data.size()+1, 4); // namesz.
685*9880d681SAndroid Build Coastguard Worker getStreamer().EmitIntValue(0, 4); // descsz = 0 (no description).
686*9880d681SAndroid Build Coastguard Worker getStreamer().EmitIntValue(1, 4); // type = NT_VERSION.
687*9880d681SAndroid Build Coastguard Worker getStreamer().EmitBytes(Data); // name.
688*9880d681SAndroid Build Coastguard Worker getStreamer().EmitIntValue(0, 1); // terminate the string.
689*9880d681SAndroid Build Coastguard Worker getStreamer().EmitValueToAlignment(4); // ensure 4 byte alignment.
690*9880d681SAndroid Build Coastguard Worker getStreamer().PopSection();
691*9880d681SAndroid Build Coastguard Worker return false;
692*9880d681SAndroid Build Coastguard Worker }
693*9880d681SAndroid Build Coastguard Worker
694*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveWeakref
695*9880d681SAndroid Build Coastguard Worker /// ::= .weakref foo, bar
ParseDirectiveWeakref(StringRef,SMLoc)696*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
697*9880d681SAndroid Build Coastguard Worker // FIXME: Share code with the other alias building directives.
698*9880d681SAndroid Build Coastguard Worker
699*9880d681SAndroid Build Coastguard Worker StringRef AliasName;
700*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(AliasName))
701*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
702*9880d681SAndroid Build Coastguard Worker
703*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::Comma))
704*9880d681SAndroid Build Coastguard Worker return TokError("expected a comma");
705*9880d681SAndroid Build Coastguard Worker
706*9880d681SAndroid Build Coastguard Worker Lex();
707*9880d681SAndroid Build Coastguard Worker
708*9880d681SAndroid Build Coastguard Worker StringRef Name;
709*9880d681SAndroid Build Coastguard Worker if (getParser().parseIdentifier(Name))
710*9880d681SAndroid Build Coastguard Worker return TokError("expected identifier in directive");
711*9880d681SAndroid Build Coastguard Worker
712*9880d681SAndroid Build Coastguard Worker MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
713*9880d681SAndroid Build Coastguard Worker
714*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
715*9880d681SAndroid Build Coastguard Worker
716*9880d681SAndroid Build Coastguard Worker getStreamer().EmitWeakReference(Alias, Sym);
717*9880d681SAndroid Build Coastguard Worker return false;
718*9880d681SAndroid Build Coastguard Worker }
719*9880d681SAndroid Build Coastguard Worker
ParseDirectiveSubsection(StringRef,SMLoc)720*9880d681SAndroid Build Coastguard Worker bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
721*9880d681SAndroid Build Coastguard Worker const MCExpr *Subsection = nullptr;
722*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement)) {
723*9880d681SAndroid Build Coastguard Worker if (getParser().parseExpression(Subsection))
724*9880d681SAndroid Build Coastguard Worker return true;
725*9880d681SAndroid Build Coastguard Worker }
726*9880d681SAndroid Build Coastguard Worker
727*9880d681SAndroid Build Coastguard Worker if (getLexer().isNot(AsmToken::EndOfStatement))
728*9880d681SAndroid Build Coastguard Worker return TokError("unexpected token in directive");
729*9880d681SAndroid Build Coastguard Worker
730*9880d681SAndroid Build Coastguard Worker getStreamer().SubSection(Subsection);
731*9880d681SAndroid Build Coastguard Worker return false;
732*9880d681SAndroid Build Coastguard Worker }
733*9880d681SAndroid Build Coastguard Worker
734*9880d681SAndroid Build Coastguard Worker namespace llvm {
735*9880d681SAndroid Build Coastguard Worker
createELFAsmParser()736*9880d681SAndroid Build Coastguard Worker MCAsmParserExtension *createELFAsmParser() {
737*9880d681SAndroid Build Coastguard Worker return new ELFAsmParser;
738*9880d681SAndroid Build Coastguard Worker }
739*9880d681SAndroid Build Coastguard Worker
740*9880d681SAndroid Build Coastguard Worker }
741