diff options
Diffstat (limited to 'lib/MC/MCParser/ELFAsmParser.cpp')
-rw-r--r-- | lib/MC/MCParser/ELFAsmParser.cpp | 108 |
1 files changed, 85 insertions, 23 deletions
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 3e2150a451e0..67e3512cc5bd 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -85,6 +85,7 @@ public: addDirectiveHandler< &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection"); + addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile"); } // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is @@ -149,6 +150,7 @@ public: bool ParseDirectiveWeakref(StringRef, SMLoc); bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); bool ParseDirectiveSubsection(StringRef, SMLoc); + bool ParseDirectiveCGProfile(StringRef, SMLoc); private: bool ParseSectionName(StringRef &SectionName); @@ -380,7 +382,6 @@ bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { return false; } -// FIXME: This is a work in progress. bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) { return ParseSectionArguments(/*IsPush=*/false, loc); } @@ -447,7 +448,7 @@ bool ELFAsmParser::parseMetadataSym(MCSymbolELF *&Associated) { Lex(); StringRef Name; if (getParser().parseIdentifier(Name)) - return true; + return TokError("invalid metadata symbol"); Associated = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name)); if (!Associated || !Associated->isInSection()) return TokError("symbol is not in a section: " + Name); @@ -480,6 +481,34 @@ static bool hasPrefix(StringRef SectionName, StringRef Prefix) { return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back(); } +// Return a set of section flags based on the section name that can then +// be augmented later, otherwise return 0 if we don't have any reasonable +// defaults. +static unsigned defaultSectionFlags(StringRef SectionName) { + + if (hasPrefix(SectionName, ".rodata.cst")) + return ELF::SHF_ALLOC | ELF::SHF_MERGE; + + if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1") + return ELF::SHF_ALLOC; + + if (SectionName == ".fini" || SectionName == ".init" || + hasPrefix(SectionName, ".text.")) + return ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; + + if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" || + hasPrefix(SectionName, ".bss.") || + hasPrefix(SectionName, ".init_array.") || + hasPrefix(SectionName, ".fini_array.") || + hasPrefix(SectionName, ".preinit_array.")) + return ELF::SHF_ALLOC | ELF::SHF_WRITE; + + if (hasPrefix(SectionName, ".tdata.") || hasPrefix(SectionName, ".tbss.")) + return ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS; + + return 0; +} + bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { StringRef SectionName; @@ -489,27 +518,13 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { StringRef TypeName; int64_t Size = 0; StringRef GroupName; - unsigned Flags = 0; const MCExpr *Subsection = nullptr; bool UseLastGroup = false; MCSymbolELF *Associated = nullptr; int64_t UniqueID = ~0; - // Set the defaults first. - if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1") - Flags |= ELF::SHF_ALLOC; - if (SectionName == ".fini" || SectionName == ".init" || - hasPrefix(SectionName, ".text.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; - if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" || - hasPrefix(SectionName, ".bss.") || - hasPrefix(SectionName, ".init_array.") || - hasPrefix(SectionName, ".fini_array.") || - hasPrefix(SectionName, ".preinit_array.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE; - if (hasPrefix(SectionName, ".tdata.") || - hasPrefix(SectionName, ".tbss.")) - Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS; + // Set the default section flags first in case no others are given. + unsigned Flags = defaultSectionFlags(SectionName); if (getLexer().is(AsmToken::Comma)) { Lex(); @@ -537,6 +552,12 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) { if (extraFlags == -1U) return TokError("unknown flag"); + + // If we found additional section flags on a known section then give a + // warning. + if (Flags && Flags != extraFlags) + Warning(loc, "setting incorrect section attributes for " + SectionName); + Flags |= extraFlags; bool Mergeable = Flags & ELF::SHF_MERGE; @@ -608,6 +629,10 @@ EndStmt: Type = ELF::SHT_X86_64_UNWIND; else if (TypeName == "llvm_odrtab") Type = ELF::SHT_LLVM_ODRTAB; + else if (TypeName == "llvm_linker_options") + Type = ELF::SHT_LLVM_LINKER_OPTIONS; + else if (TypeName == "llvm_call_graph_profile") + Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE; else if (TypeName.getAsInteger(0, Type)) return TokError("unknown section type"); } @@ -767,12 +792,8 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { if (AliasName.find('@') == StringRef::npos) return TokError("expected a '@' in the name"); - MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - const MCExpr *Value = MCSymbolRefExpr::create(Sym, getContext()); - - getStreamer().EmitAssignment(Alias, Value); - getStreamer().emitELFSymverDirective(Alias, Sym); + getStreamer().emitELFSymverDirective(AliasName, Sym); return false; } @@ -842,6 +863,47 @@ bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) { return false; } +/// ParseDirectiveCGProfile +/// ::= .cg_profile identifier, identifier, <number> +bool ELFAsmParser::ParseDirectiveCGProfile(StringRef, SMLoc) { + StringRef From; + SMLoc FromLoc = getLexer().getLoc(); + if (getParser().parseIdentifier(From)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected a comma"); + Lex(); + + StringRef To; + SMLoc ToLoc = getLexer().getLoc(); + if (getParser().parseIdentifier(To)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected a comma"); + Lex(); + + int64_t Count; + if (getParser().parseIntToken( + Count, "expected integer count in '.cg_profile' directive")) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + MCSymbol *FromSym = getContext().getOrCreateSymbol(From); + MCSymbol *ToSym = getContext().getOrCreateSymbol(To); + + getStreamer().emitCGProfileEntry( + MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(), + FromLoc), + MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(), + ToLoc), + Count); + return false; +} + namespace llvm { MCAsmParserExtension *createELFAsmParser() { |