From f7c5fbb1ca982eebad6000d2ca53d8ad2cb922ff Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 30 Sep 2015 17:23:26 +0000 Subject: [PATCH] ELF2: Create LinkerScript.cpp and move code from DriverUtils to there. llvm-svn: 248920 --- lld/ELF/CMakeLists.txt | 1 + lld/ELF/DriverUtils.cpp | 137 ---------------------------------- lld/ELF/LinkerScript.cpp | 156 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 137 deletions(-) create mode 100644 lld/ELF/LinkerScript.cpp diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index 3f98a9cb7df4..20e039c77a30 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -8,6 +8,7 @@ add_llvm_library(lldELF2 Error.cpp InputFiles.cpp InputSection.cpp + LinkerScript.cpp OutputSections.cpp SymbolTable.cpp Symbols.cpp diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp index cf97c9312724..704d7c9ec124 100644 --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.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 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 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 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 LinkerScript::tokenize(StringRef S) { - std::vector 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(); -} diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp new file mode 100644 index 000000000000..746af74b6b90 --- /dev/null +++ b/lld/ELF/LinkerScript.cpp @@ -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 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 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 LinkerScript::tokenize(StringRef S) { + std::vector 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(); +}