diff options
author | Nico Rieck <nico.rieck@gmail.com> | 2013-07-04 21:32:07 +0000 |
---|---|---|
committer | Nico Rieck <nico.rieck@gmail.com> | 2013-07-04 21:32:07 +0000 |
commit | a6d343a688073664b3a80aa117e0d3cbecf28014 (patch) | |
tree | 8a200175ba18e94d9446e29131c5d19f234e0893 /lib/MC | |
parent | e7006bb04bd881478fe24d6fbb3051ba3f63d746 (diff) | |
download | external_llvm-a6d343a688073664b3a80aa117e0d3cbecf28014.zip external_llvm-a6d343a688073664b3a80aa117e0d3cbecf28014.tar.gz external_llvm-a6d343a688073664b3a80aa117e0d3cbecf28014.tar.bz2 |
MC: Add .section directive to COFF
Supports GAS flags "abdnrswxy". No support for alignment or subsections.
Fixes PR16366.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185669 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/MCParser/COFFAsmParser.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index ad8f84c..c2a2261 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -35,6 +35,9 @@ class COFFAsmParser : public MCAsmParserExtension { unsigned Characteristics, SectionKind Kind); + bool ParseSectionName(StringRef &SectionName); + bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); + virtual void Initialize(MCAsmParser &Parser) { // Call the base implementation. MCAsmParserExtension::Initialize(Parser); @@ -42,6 +45,7 @@ class COFFAsmParser : public MCAsmParserExtension { addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); + addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); @@ -100,6 +104,7 @@ class COFFAsmParser : public MCAsmParserExtension { SectionKind::getBSS()); } + bool ParseDirectiveSection(StringRef, SMLoc); bool ParseDirectiveDef(StringRef, SMLoc); bool ParseDirectiveScl(StringRef, SMLoc); bool ParseDirectiveType(StringRef, SMLoc); @@ -130,6 +135,119 @@ public: } // end annonomous namespace. +static SectionKind computeSectionKind(unsigned Flags) { + if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) + return SectionKind::getText(); + if (Flags & COFF::IMAGE_SCN_MEM_READ && + (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) + return SectionKind::getReadOnly(); + return SectionKind::getDataRel(); +} + +bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { + enum { + None = 0, + Alloc = 1 << 0, + Code = 1 << 1, + Load = 1 << 2, + InitData = 1 << 3, + Shared = 1 << 4, + NoLoad = 1 << 5, + NoRead = 1 << 6, + NoWrite = 1 << 7 + }; + + bool ReadOnlyRemoved = false; + unsigned SecFlags = None; + + for (unsigned i = 0; i < FlagsString.size(); ++i) { + switch (FlagsString[i]) { + case 'a': + // Ignored. + break; + + case 'b': // bss section + SecFlags |= Alloc; + if (SecFlags & InitData) + return TokError("conflicting section flags 'b' and 'd'."); + SecFlags &= ~Load; + break; + + case 'd': // data section + SecFlags |= InitData; + if (SecFlags & Alloc) + return TokError("conflicting section flags 'b' and 'd'."); + SecFlags &= ~NoWrite; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 'n': // section is not loaded + SecFlags |= NoLoad; + SecFlags &= ~Load; + break; + + case 'r': // read-only + ReadOnlyRemoved = false; + SecFlags |= NoWrite; + if ((SecFlags & Code) == 0) + SecFlags |= InitData; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 's': // shared section + SecFlags |= Shared | InitData; + SecFlags &= ~NoWrite; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + break; + + case 'w': // writable + SecFlags &= ~NoWrite; + ReadOnlyRemoved = true; + break; + + case 'x': // executable section + SecFlags |= Code; + if ((SecFlags & NoLoad) == 0) + SecFlags |= Load; + if (!ReadOnlyRemoved) + SecFlags |= NoWrite; + break; + + case 'y': // not readable + SecFlags |= NoRead | NoWrite; + break; + + default: + return TokError("unknown flag"); + } + } + + *Flags = 0; + + if (SecFlags == None) + SecFlags = InitData; + + if (SecFlags & Code) + *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; + if (SecFlags & InitData) + *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; + if ((SecFlags & Alloc) && (SecFlags & Load) == 0) + *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + if (SecFlags & NoLoad) + *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; + if ((SecFlags & NoRead) == 0) + *Flags |= COFF::IMAGE_SCN_MEM_READ; + if ((SecFlags & NoWrite) == 0) + *Flags |= COFF::IMAGE_SCN_MEM_WRITE; + if (SecFlags & Shared) + *Flags |= COFF::IMAGE_SCN_MEM_SHARED; + + return false; +} + /// ParseDirectiveSymbolAttribute /// ::= { ".weak", ... } [ identifier ( , identifier )* ] bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { @@ -174,6 +292,60 @@ bool COFFAsmParser::ParseSectionSwitch(StringRef Section, return false; } +bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { + if (!getLexer().is(AsmToken::Identifier)) + return true; + + SectionName = getTok().getIdentifier(); + Lex(); + return false; +} + +// .section name [, "flags"] +// +// Supported flags: +// a: Ignored. +// b: BSS section (uninitialized data) +// d: data section (initialized data) +// n: Discardable section +// r: Readable section +// s: Shared section +// w: Writable section +// x: Executable section +// y: Not-readable section (clears 'r') +// +// Subsections are not supported. +bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + StringRef SectionName; + + if (ParseSectionName(SectionName)) + return TokError("expected identifier in directive"); + + unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in directive"); + + StringRef FlagsStr = getTok().getStringContents(); + Lex(); + + if (ParseSectionFlags(FlagsStr, &Flags)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + SectionKind Kind = computeSectionKind(Flags); + ParseSectionSwitch(SectionName, Flags, Kind); + return false; +} + bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { StringRef SymbolName; |