[ELF] Support for parsing OUTPUT command in LinkerScript

Differential Revision:	D7326
Reviewed by:	rafaelauler, shankarke, ruiu

llvm-svn: 227786
This commit is contained in:
Davide Italiano
2015-02-02 06:21:23 +00:00
parent e644b75782
commit 5cbde851ed
3 changed files with 61 additions and 0 deletions

View File

@@ -78,6 +78,7 @@ public:
kw_provide_hidden,
kw_only_if_ro,
kw_only_if_rw,
kw_output,
kw_output_arch,
kw_output_format,
kw_overlay,
@@ -149,6 +150,7 @@ public:
Entry,
Group,
InputSectionsCmd,
Output,
OutputArch,
OutputFormat,
OutputSectionDescription,
@@ -171,6 +173,23 @@ private:
Kind _kind;
};
class Output : public Command {
public:
explicit Output(StringRef outputFileName)
: Command(Kind::Output), _outputFileName(outputFileName) {}
static bool classof(const Command *c) { return c->getKind() == Kind::Output; }
void dump(raw_ostream &os) const override {
os << "OUTPUT(" << _outputFileName << ")\n";
}
StringRef getOutputFileName() const { return _outputFileName; }
private:
StringRef _outputFileName;
};
class OutputFormat : public Command {
public:
explicit OutputFormat(StringRef format) : Command(Kind::OutputFormat) {
@@ -834,6 +853,13 @@ private:
// ==== High-level commands parsing ====
/// Parse the OUTPUT linker script command.
/// Example:
/// OUTPUT(/path/to/file)
/// ^~~~> parseOutput()
///
Output *parseOutput();
/// Parse the OUTPUT_FORMAT linker script command.
/// Example:
///

View File

@@ -69,6 +69,7 @@ void Token::dump(raw_ostream &os) const {
CASE(kw_provide_hidden)
CASE(kw_only_if_ro)
CASE(kw_only_if_rw)
CASE(kw_output)
CASE(kw_output_arch)
CASE(kw_output_format)
CASE(kw_overlay)
@@ -515,6 +516,7 @@ void Lexer::lex(Token &tok) {
.Case("KEEP", Token::kw_keep)
.Case("ONLY_IF_RO", Token::kw_only_if_ro)
.Case("ONLY_IF_RW", Token::kw_only_if_rw)
.Case("OUTPUT", Token::kw_output)
.Case("OUTPUT_ARCH", Token::kw_output_arch)
.Case("OUTPUT_FORMAT", Token::kw_output_format)
.Case("OVERLAY", Token::kw_overlay)
@@ -901,6 +903,13 @@ LinkerScript *Parser::parse() {
case Token::semicolon:
consumeToken();
break;
case Token::kw_output: {
auto output = parseOutput();
if (!output)
return nullptr;
_script._commands.push_back(output);
break;
}
case Token::kw_output_format: {
auto outputFormat = parseOutputFormat();
if (!outputFormat)
@@ -1211,6 +1220,27 @@ const Expression *Parser::parseTernaryCondOp(const Expression *lhs) {
return new (_alloc) TernaryConditional(lhs, trueExpr, falseExpr);
}
// Parse OUTPUT(ident)
Output *Parser::parseOutput() {
assert(_tok._kind == Token::kw_output && "Expected OUTPUT");
consumeToken();
if (!expectAndConsume(Token::l_paren, "expected ("))
return nullptr;
if (_tok._kind != Token::identifier) {
error(_tok, "Expected identifier in OUTPUT.");
return nullptr;
}
auto ret = new (_alloc) Output(_tok._range);
consumeToken();
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
return ret;
}
// Parse OUTPUT_FORMAT(ident)
OutputFormat *Parser::parseOutputFormat() {
assert(_tok._kind == Token::kw_output_format && "Expected OUTPUT_FORMAT!");

View File

@@ -3,6 +3,7 @@
OUTPUT_ARCH(i386:x86_64)
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT("/out/foo")
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) -lm -l:libgcc.a )
ENTRY(init)
@@ -19,6 +20,10 @@ CHECK: identifier: elf64-x86-64
CHECK: comma: ,
CHECK: identifier: elf64-x86-64
CHECK: r_paren: )
CHECK: kw_output: OUTPUT
CHECK: l_paren: (
CHECK: identifier: /out/foo
CHECK: r_paren: )
CHECK: kw_group: GROUP
CHECK: l_paren: (
CHECK: identifier: /lib/x86_64-linux-gnu/libc.so.6