Index: ELF/CMakeLists.txt =================================================================== --- ELF/CMakeLists.txt +++ ELF/CMakeLists.txt @@ -18,7 +18,6 @@ Relocations.cpp ScriptParser.cpp Strings.cpp - SymbolListFile.cpp SymbolTable.cpp Symbols.cpp Target.cpp Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -15,7 +15,6 @@ #include "InputSection.h" #include "LinkerScript.h" #include "Strings.h" -#include "SymbolListFile.h" #include "SymbolTable.h" #include "Target.h" #include "Writer.h" Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -30,6 +30,10 @@ typedef std::function Expr; +void parseDynamicList(MemoryBufferRef MB); + +void parseVersionScript(MemoryBufferRef MB); + // Parses a linker script. Calling this function updates // Config and ScriptConfig. void readLinkerScript(MemoryBufferRef MB); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -43,6 +43,146 @@ ScriptConfiguration *elf::ScriptConfig; +// Parse the --dynamic-list argument. A dynamic list is in the form +// +// { symbol1; symbol2; [...]; symbolN }; +// +// Multiple groups can be defined in the same file, and they are merged +// into a single group. + +namespace { +class DynamicListParser final : public ScriptParserBase { +public: + DynamicListParser(StringRef S) : ScriptParserBase(S) {} + void run(); +}; +} // end anonymous namespace + +void DynamicListParser::run() { + while (!atEOF()) { + expect("{"); + while (!Error) { + Config->DynamicList.push_back(next()); + expect(";"); + if (skip("}")) + break; + } + expect(";"); + } +} + +void elf::parseDynamicList(MemoryBufferRef MB) { + DynamicListParser(MB.getBuffer()).run(); +} + +// Parse the --version-script argument. We currently only accept the following +// version script syntax: +// +// { [ global: symbol1; symbol2; [...]; symbolN; ] local: *; }; +// + +namespace { +class VersionScriptParser final : public ScriptParserBase { +public: + VersionScriptParser(StringRef S) : ScriptParserBase(S) {} + + void run(); + +private: + void parseExtern(std::vector *Globals); + void parseVersion(StringRef VerStr); + void parseGlobal(StringRef VerStr); + void parseLocal(); +}; +} // end anonymous namespace + +void VersionScriptParser::parseVersion(StringRef VerStr) { + // Identifiers start at 2 because 0 and 1 are reserved + // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants. + size_t VersionId = Config->VersionDefinitions.size() + 2; + Config->VersionDefinitions.push_back({VerStr, VersionId}); + + if (skip("global:") || peek() != "local:") + parseGlobal(VerStr); + if (skip("local:")) + parseLocal(); + expect("}"); + + // Each version may have a parent version. For example, "Ver2" defined as + // "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" as a parent. This + // version hierarchy is, probably against your instinct, purely for human; the + // runtime doesn't care about them at all. In LLD, we simply skip the token. + if (!VerStr.empty() && peek() != ";") + next(); + expect(";"); +} + +void VersionScriptParser::parseLocal() { + Config->DefaultSymbolVersion = VER_NDX_LOCAL; + expect("*"); + expect(";"); +} + +void VersionScriptParser::parseExtern(std::vector *Globals) { + expect("C++"); + expect("{"); + + for (;;) { + if (peek() == "}" || Error) + break; + Globals->push_back({next(), true}); + expect(";"); + } + + expect("}"); + expect(";"); +} + +void VersionScriptParser::parseGlobal(StringRef VerStr) { + std::vector *Globals; + if (VerStr.empty()) + Globals = &Config->VersionScriptGlobals; + else + Globals = &Config->VersionDefinitions.back().Globals; + + for (;;) { + if (skip("extern")) + parseExtern(Globals); + + StringRef Cur = peek(); + if (Cur == "}" || Cur == "local:" || Error) + return; + next(); + Globals->push_back({Cur, false}); + expect(";"); + } +} + +void VersionScriptParser::run() { + StringRef Msg = "anonymous version definition is used in " + "combination with other version definitions"; + if (skip("{")) { + parseVersion(""); + if (!atEOF()) + setError(Msg); + return; + } + + while (!atEOF() && !Error) { + StringRef VerStr = next(); + if (VerStr == "{") { + setError(Msg); + return; + } + expect("{"); + parseVersion(VerStr); + } +} + +void elf::parseVersionScript(MemoryBufferRef MB) { + VersionScriptParser(MB.getBuffer()).run(); +} + template static void addRegular(SymbolAssignment *Cmd) { Symbol *Sym = Symtab::X->addRegular(Cmd->Name, STB_GLOBAL, STV_DEFAULT); Index: ELF/SymbolListFile.h =================================================================== --- ELF/SymbolListFile.h +++ ELF/SymbolListFile.h @@ -1,25 +0,0 @@ -//===- SymbolListFile.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_ELF_SYMBOL_LIST_FILE_H -#define LLD_ELF_SYMBOL_LIST_FILE_H - -#include "lld/Core/LLVM.h" -#include "llvm/Support/MemoryBuffer.h" - -namespace lld { -namespace elf { - -void parseDynamicList(MemoryBufferRef MB); -void parseVersionScript(MemoryBufferRef MB); - -} // namespace elf -} // namespace lld - -#endif Index: ELF/SymbolListFile.cpp =================================================================== --- ELF/SymbolListFile.cpp +++ ELF/SymbolListFile.cpp @@ -1,167 +0,0 @@ -//===- SymbolListFile.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 Driver or Config object. -// -//===----------------------------------------------------------------------===// - -#include "SymbolListFile.h" -#include "Config.h" -#include "ScriptParser.h" -#include "llvm/Support/MemoryBuffer.h" - -using namespace llvm; -using namespace llvm::ELF; - -using namespace lld; -using namespace lld::elf; - -// Parse the --dynamic-list argument. A dynamic list is in the form -// -// { symbol1; symbol2; [...]; symbolN }; -// -// Multiple groups can be defined in the same file, and they are merged -// into a single group. - -namespace { -class DynamicListParser final : public ScriptParserBase { -public: - DynamicListParser(StringRef S) : ScriptParserBase(S) {} - void run(); -}; -} // end anonymous namespace - -void DynamicListParser::run() { - while (!atEOF()) { - expect("{"); - while (!Error) { - Config->DynamicList.push_back(next()); - expect(";"); - if (skip("}")) - break; - } - expect(";"); - } -} - -void elf::parseDynamicList(MemoryBufferRef MB) { - DynamicListParser(MB.getBuffer()).run(); -} - -// Parse the --version-script argument. We currently only accept the following -// version script syntax: -// -// { [ global: symbol1; symbol2; [...]; symbolN; ] local: *; }; -// -// No wildcards are supported, other than for the local entry. Symbol versioning -// is also not supported. - -namespace { -class VersionScriptParser final : public ScriptParserBase { -public: - VersionScriptParser(StringRef S) : ScriptParserBase(S) {} - - void run(); - -private: - void parseExtern(std::vector *Globals); - void parseVersion(StringRef VerStr); - void parseGlobal(StringRef VerStr); - void parseLocal(); -}; -} // end anonymous namespace - -void VersionScriptParser::parseVersion(StringRef VerStr) { - // Identifiers start at 2 because 0 and 1 are reserved - // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants. - size_t VersionId = Config->VersionDefinitions.size() + 2; - Config->VersionDefinitions.push_back({VerStr, VersionId}); - - if (skip("global:") || peek() != "local:") - parseGlobal(VerStr); - if (skip("local:")) - parseLocal(); - expect("}"); - - // Each version may have a parent version. For example, "Ver2" defined as - // "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" as a parent. This - // version hierarchy is, probably against your instinct, purely for human; the - // runtime doesn't care about them at all. In LLD, we simply skip the token. - if (!VerStr.empty() && peek() != ";") - next(); - expect(";"); -} - -void VersionScriptParser::parseLocal() { - Config->DefaultSymbolVersion = VER_NDX_LOCAL; - expect("*"); - expect(";"); -} - -void VersionScriptParser::parseExtern(std::vector *Globals) { - expect("C++"); - expect("{"); - - for (;;) { - if (peek() == "}" || Error) - break; - Globals->push_back({next(), true}); - expect(";"); - } - - expect("}"); - expect(";"); -} - -void VersionScriptParser::parseGlobal(StringRef VerStr) { - std::vector *Globals; - if (VerStr.empty()) - Globals = &Config->VersionScriptGlobals; - else - Globals = &Config->VersionDefinitions.back().Globals; - - for (;;) { - if (skip("extern")) - parseExtern(Globals); - - StringRef Cur = peek(); - if (Cur == "}" || Cur == "local:" || Error) - return; - next(); - Globals->push_back({Cur, false}); - expect(";"); - } -} - -void VersionScriptParser::run() { - StringRef Msg = "anonymous version definition is used in " - "combination with other version definitions"; - if (skip("{")) { - parseVersion(""); - if (!atEOF()) - setError(Msg); - return; - } - - while (!atEOF() && !Error) { - StringRef VerStr = next(); - if (VerStr == "{") { - setError(Msg); - return; - } - expect("{"); - parseVersion(VerStr); - } -} - -void elf::parseVersionScript(MemoryBufferRef MB) { - VersionScriptParser(MB.getBuffer()).run(); -} Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -19,7 +19,6 @@ #include "Error.h" #include "LinkerScript.h" #include "Strings.h" -#include "SymbolListFile.h" #include "Symbols.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/StringSaver.h"