forked from OSchip/llvm-project
ELF2: Create LinkerScript.cpp and move code from DriverUtils to there.
llvm-svn: 248920
This commit is contained in:
parent
bf506b7d48
commit
f7c5fbb1ca
|
@ -8,6 +8,7 @@ add_llvm_library(lldELF2
|
|||
Error.cpp
|
||||
InputFiles.cpp
|
||||
InputSection.cpp
|
||||
LinkerScript.cpp
|
||||
OutputSections.cpp
|
||||
SymbolTable.cpp
|
||||
Symbols.cpp
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue