Index: ELF/CMakeLists.txt =================================================================== --- ELF/CMakeLists.txt +++ ELF/CMakeLists.txt @@ -5,6 +5,7 @@ add_lld_library(lldELF Driver.cpp DriverUtils.cpp + DynamicList.cpp Error.cpp ICF.cpp InputFiles.cpp Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -57,6 +57,7 @@ bool Bsymbolic; bool BsymbolicFunctions; bool Demangle = true; + bool DynamicList; bool DisableVerify; bool DiscardAll; bool DiscardLocals; Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -30,6 +30,7 @@ private: std::vector getArchiveMembers(MemoryBufferRef MB); void readConfigs(llvm::opt::InputArgList &Args); + void readDynamicList(StringRef Path); void createFiles(llvm::opt::InputArgList &Args); template void link(llvm::opt::InputArgList &Args); Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -9,6 +9,7 @@ #include "Driver.h" #include "Config.h" +#include "DynamicList.h" #include "Error.h" #include "ICF.h" #include "InputFiles.h" @@ -38,9 +39,11 @@ Configuration C; LinkerDriver D; LinkerScript LS; + DynamicList DL; Config = &C; Driver = &D; Script = &LS; + DynList = &DL; Driver->main(Args); return !HasError; } @@ -136,6 +139,19 @@ } } +void LinkerDriver::readDynamicList(StringRef Path) { + using namespace llvm::sys::fs; + auto MBOrErr = MemoryBuffer::getFile(Path); + if (!MBOrErr) { + error(MBOrErr, "cannot open " + Path); + return; + } + std::unique_ptr &MB = *MBOrErr; + MemoryBufferRef MBRef = MB->getMemBufferRef(); + OwningMBs.push_back(std::move(MB)); // take MB ownership + DynList->read(MBRef); +} + // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { std::string Path = searchLibrary(Name); @@ -303,6 +319,9 @@ Config->OutputFile = getString(Args, OPT_o); Config->SoName = getString(Args, OPT_soname); Config->Sysroot = getString(Args, OPT_sysroot); + Config->DynamicList = Args.hasArg(OPT_dynamic_list); + if (Config->DynamicList) + readDynamicList(getString(Args, OPT_dynamic_list)); Config->Optimize = getInteger(Args, OPT_O, 0); Config->LtoO = getInteger(Args, OPT_lto_O, 2); Index: ELF/DynamicList.h =================================================================== --- /dev/null +++ ELF/DynamicList.h @@ -0,0 +1,40 @@ +//===- DynamicList.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_DYNAMIC_LIST_H +#define LLD_ELF_DYNAMIC_LIST_H + +#include "lld/Core/LLVM.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/MemoryBuffer.h" + +namespace lld { +namespace elf { + +class DynamicListParser; + +class DynamicList { + friend class DynamicListParser; + +public: + void read(MemoryBufferRef MB); + + bool isInDynamicList(StringRef Symbol); + +private: + llvm::StringSet<> ExactMatch; +}; + +extern DynamicList *DynList; + +} // namespace elf +} // namespace lld + +#endif Index: ELF/DynamicList.cpp =================================================================== --- /dev/null +++ ELF/DynamicList.cpp @@ -0,0 +1,79 @@ +//===- 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 Driver or Config object. +// +//===----------------------------------------------------------------------===// + +#include "DynamicList.h" +#include "Config.h" +#include "Driver.h" +#include "ScriptParser.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/StringSaver.h" + +using namespace llvm; +using namespace llvm::object; +using namespace lld; +using namespace lld::elf; + +DynamicList *elf::DynList; + +// 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 +// in only one definition. + +class elf::DynamicListParser final : public ScriptParserBase { +public: + DynamicListParser(StringRef S) : ScriptParserBase(S) {} + + void run() final; + +private: + void readGroup(); + void readEntry(); +}; + +// Parse the default group definition using C language symbol name. +void DynamicListParser::readGroup() { + expect("{"); + while (!Error) { + readEntry(); + expect(";"); + if (peek() == "}") { + next(); + break; + } + } + expect(";"); +} + +void DynamicListParser::readEntry() { + DynList->ExactMatch.insert(next()); +} + +void DynamicListParser::run() { + while (!atEOF()) + readGroup(); +} + +void DynamicList::read(MemoryBufferRef MB) { + DynamicListParser(MB.getBuffer()).run(); +} + +bool DynamicList::isInDynamicList(StringRef Symbol) { + return ExactMatch.find(Symbol) != ExactMatch.end(); +} Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -166,6 +166,9 @@ def z : JoinedOrSeparate<["-"], "z">, MetaVarName<"