bool ParseSectionSwitch(StringRef Section, unsigned Type,
unsigned Flags, SectionKind Kind);
+ bool SeenIdent;
public:
- ELFAsmParser() {}
+ ELFAsmParser() : SeenIdent(false) {
+ BracketExpressionsSupported = true;
+ }
virtual void Initialize(MCAsmParser &Parser) {
// Call the base implementation.
AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
- AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
- AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
- AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local");
- AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseDirectivePushSection>(".pushsection");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
+ AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
+ AddDirectiveHandler<
+ &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
}
// FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
ELF::SHF_WRITE,
SectionKind::getDataRel());
}
+ bool ParseDirectivePushSection(StringRef, SMLoc);
+ bool ParseDirectivePopSection(StringRef, SMLoc);
bool ParseDirectiveSection(StringRef, SMLoc);
bool ParseDirectiveSize(StringRef, SMLoc);
bool ParseDirectivePrevious(StringRef, SMLoc);
bool ParseDirectiveIdent(StringRef, SMLoc);
bool ParseDirectiveSymver(StringRef, SMLoc);
bool ParseDirectiveWeakref(StringRef, SMLoc);
+ bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
private:
bool ParseSectionName(StringRef &SectionName);
}
+/// ParseDirectiveSymbolAttribute
+/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
+bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
+ MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
+ .Case(".weak", MCSA_Weak)
+ .Case(".local", MCSA_Local)
+ .Case(".hidden", MCSA_Hidden)
+ .Case(".internal", MCSA_Internal)
+ .Case(".protected", MCSA_Protected)
+ .Default(MCSA_Invalid);
+ assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ StringRef Name;
+
+ if (getParser().ParseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
+
+ getStreamer().EmitSymbolAttribute(Sym, Attr);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+
bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
unsigned Flags, SectionKind Kind) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return flags;
}
+bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
+ getStreamer().PushSection();
+
+ if (ParseDirectiveSection(s, loc)) {
+ getStreamer().PopSection();
+ return true;
+ }
+
+ return false;
+}
+
+bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
+ if (!getStreamer().PopSection())
+ return TokError(".popsection without corresponding .pushsection");
+ return false;
+}
+
// FIXME: This is a work in progress.
bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
StringRef SectionName;
bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
const MCSection *PreviousSection = getStreamer().getPreviousSection();
- if (PreviousSection != NULL)
- getStreamer().SwitchSection(PreviousSection);
+ if (PreviousSection == NULL)
+ return TokError(".previous without corresponding .section");
+ getStreamer().SwitchSection(PreviousSection);
return false;
}
.Case("common", MCSA_ELF_TypeCommon)
.Case("notype", MCSA_ELF_TypeNoType)
.Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
+ .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction)
.Default(MCSA_Invalid);
if (Attr == MCSA_Invalid)
Lex();
- const MCSection *OldSection = getStreamer().getCurrentSection();
const MCSection *Comment =
getContext().getELFSection(".comment", ELF::SHT_PROGBITS,
ELF::SHF_MERGE |
SectionKind::getReadOnly(),
1, "");
- static bool First = true;
-
+ getStreamer().PushSection();
getStreamer().SwitchSection(Comment);
- if (First)
+ if (!SeenIdent) {
getStreamer().EmitIntValue(0, 1);
- First = false;
+ SeenIdent = true;
+ }
getStreamer().EmitBytes(Data, 0);
getStreamer().EmitIntValue(0, 1);
- getStreamer().SwitchSection(OldSection);
+ getStreamer().PopSection();
return false;
}