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