ELF2: Create LinkerScript.cpp and move code from DriverUtils to there.

llvm-svn: 248920
This commit is contained in:
Rui Ueyama 2015-09-30 17:23:26 +00:00
parent bf506b7d48
commit f7c5fbb1ca
3 changed files with 157 additions and 137 deletions

View File

@ -8,6 +8,7 @@ add_llvm_library(lldELF2
Error.cpp
InputFiles.cpp
InputSection.cpp
LinkerScript.cpp
OutputSections.cpp
SymbolTable.cpp
Symbols.cpp

View File

@ -13,14 +13,10 @@
//
//===----------------------------------------------------------------------===//
#include "Config.h"
#include "Driver.h"
#include "Error.h"
#include "SymbolTable.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/StringSaver.h"
using namespace llvm;
@ -79,136 +75,3 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
return Args;
}
// Parser and evaluator of the linker script.
// Results are directly written to the Config object.
namespace {
class LinkerScript {
public:
LinkerScript(SymbolTable *T, StringRef S) : Symtab(T), Tokens(tokenize(S)) {}
void run();
private:
static std::vector<StringRef> tokenize(StringRef S);
static StringRef skipSpace(StringRef S);
StringRef next();
bool atEOF() { return Tokens.size() == Pos; }
void expect(StringRef Expect);
void readAsNeeded();
void readGroup();
void readOutputFormat();
SymbolTable *Symtab;
std::vector<StringRef> Tokens;
size_t Pos = 0;
};
}
void LinkerScript::run() {
while (!atEOF()) {
StringRef Tok = next();
if (Tok == "GROUP") {
readGroup();
} else if (Tok == "OUTPUT_FORMAT") {
readOutputFormat();
} else {
error("unknown directive: " + Tok);
}
}
}
// Split S into linker script tokens.
std::vector<StringRef> LinkerScript::tokenize(StringRef S) {
std::vector<StringRef> Ret;
for (;;) {
S = skipSpace(S);
if (S.empty())
return Ret;
// Quoted token
if (S.startswith("\"")) {
size_t E = S.find("\"", 1);
if (E == StringRef::npos)
error("unclosed quote");
Ret.push_back(S.substr(1, E));
S = S.substr(E + 1);
continue;
}
// Unquoted token
size_t Pos = S.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789_.$/\\~=+[]*?-:");
// A character that cannot start a word (which is usually a
// punctuation) forms a single character token.
if (Pos == 0)
Pos = 1;
Ret.push_back(S.substr(0, Pos));
S = S.substr(Pos);
}
}
// Skip leading whitespace characters or /**/-style comments.
StringRef LinkerScript::skipSpace(StringRef S) {
for (;;) {
if (S.startswith("/*")) {
size_t E = S.find("*/", 2);
if (E == StringRef::npos)
error("unclosed comment in a linker script");
S = S.substr(E + 2);
continue;
}
size_t Size = S.size();
S = S.ltrim();
if (S.size() == Size)
return S;
}
}
StringRef LinkerScript::next() {
if (Pos == Tokens.size())
error("unexpected EOF");
return Tokens[Pos++];
}
void LinkerScript::expect(StringRef Expect) {
StringRef Tok = next();
if (Tok != Expect)
error(Expect + " expected, but got " + Tok);
}
void LinkerScript::readAsNeeded() {
expect("(");
for (;;) {
StringRef Tok = next();
if (Tok == ")")
return;
Symtab->addFile(createFile(openFile(Tok)));
}
}
void LinkerScript::readGroup() {
expect("(");
for (;;) {
StringRef Tok = next();
if (Tok == ")")
return;
if (Tok == "AS_NEEDED") {
readAsNeeded();
continue;
}
Symtab->addFile(createFile(openFile(Tok)));
}
}
void LinkerScript::readOutputFormat() {
// Error checking only for now.
expect("(");
next();
expect(")");
}
void lld::elf2::readLinkerScript(SymbolTable *Symtab, MemoryBufferRef MB) {
LinkerScript(Symtab, MB.getBuffer()).run();
}

156
lld/ELF/LinkerScript.cpp Normal file
View File

@ -0,0 +1,156 @@
//===- LinkerScript.cpp ---------------------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the parser/evaluator of the linker script.
// It does not construct an AST but consume linker script directives directly.
// Results are written to Symtab or Config object.
//
//===----------------------------------------------------------------------===//
#include "Config.h"
#include "Driver.h"
#include "SymbolTable.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
using namespace llvm;
using namespace lld;
using namespace lld::elf2;
namespace {
class LinkerScript {
public:
LinkerScript(SymbolTable *T, StringRef S) : Symtab(T), Tokens(tokenize(S)) {}
void run();
private:
static std::vector<StringRef> tokenize(StringRef S);
static StringRef skipSpace(StringRef S);
StringRef next();
bool atEOF() { return Tokens.size() == Pos; }
void expect(StringRef Expect);
void readAsNeeded();
void readGroup();
void readOutputFormat();
SymbolTable *Symtab;
std::vector<StringRef> Tokens;
size_t Pos = 0;
};
}
void LinkerScript::run() {
while (!atEOF()) {
StringRef Tok = next();
if (Tok == "GROUP") {
readGroup();
} else if (Tok == "OUTPUT_FORMAT") {
readOutputFormat();
} else {
error("unknown directive: " + Tok);
}
}
}
// Split S into linker script tokens.
std::vector<StringRef> LinkerScript::tokenize(StringRef S) {
std::vector<StringRef> Ret;
for (;;) {
S = skipSpace(S);
if (S.empty())
return Ret;
// Quoted token
if (S.startswith("\"")) {
size_t E = S.find("\"", 1);
if (E == StringRef::npos)
error("unclosed quote");
Ret.push_back(S.substr(1, E));
S = S.substr(E + 1);
continue;
}
// Unquoted token
size_t Pos = S.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789_.$/\\~=+[]*?-:");
// A character that cannot start a word (which is usually a
// punctuation) forms a single character token.
if (Pos == 0)
Pos = 1;
Ret.push_back(S.substr(0, Pos));
S = S.substr(Pos);
}
}
// Skip leading whitespace characters or /**/-style comments.
StringRef LinkerScript::skipSpace(StringRef S) {
for (;;) {
if (S.startswith("/*")) {
size_t E = S.find("*/", 2);
if (E == StringRef::npos)
error("unclosed comment in a linker script");
S = S.substr(E + 2);
continue;
}
size_t Size = S.size();
S = S.ltrim();
if (S.size() == Size)
return S;
}
}
StringRef LinkerScript::next() {
if (Pos == Tokens.size())
error("unexpected EOF");
return Tokens[Pos++];
}
void LinkerScript::expect(StringRef Expect) {
StringRef Tok = next();
if (Tok != Expect)
error(Expect + " expected, but got " + Tok);
}
void LinkerScript::readAsNeeded() {
expect("(");
for (;;) {
StringRef Tok = next();
if (Tok == ")")
return;
Symtab->addFile(createFile(openFile(Tok)));
}
}
void LinkerScript::readGroup() {
expect("(");
for (;;) {
StringRef Tok = next();
if (Tok == ")")
return;
if (Tok == "AS_NEEDED") {
readAsNeeded();
continue;
}
Symtab->addFile(createFile(openFile(Tok)));
}
}
void LinkerScript::readOutputFormat() {
// Error checking only for now.
expect("(");
next();
expect(")");
}
// Entry point. The other functions or classes are private to this file.
void lld::elf2::readLinkerScript(SymbolTable *Symtab, MemoryBufferRef MB) {
LinkerScript(Symtab, MB.getBuffer()).run();
}