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 @@ -48,6 +48,7 @@ llvm::StringRef SoName; llvm::StringRef Sysroot; std::string RPath; + std::vector DynamicList; std::vector SearchPaths; std::vector Undefined; bool AllowMultipleDefinition; Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -12,6 +12,7 @@ #include "SymbolTable.h" #include "lld/Core/LLVM.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/raw_ostream.h" @@ -29,7 +30,9 @@ private: std::vector getArchiveMembers(MemoryBufferRef MB); + llvm::Optional readFile(StringRef Path); 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 @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "Driver.h" +#include "DynamicList.h" #include "Config.h" #include "Error.h" #include "ICF.h" @@ -100,14 +101,10 @@ using namespace llvm::sys::fs; if (Config->Verbose || Config->Trace) llvm::outs() << Path << "\n"; - auto MBOrErr = MemoryBuffer::getFile(Path); - if (!MBOrErr) { - error(MBOrErr, "cannot open " + Path); + llvm::Optional Buffer = readFile(Path); + if (!Buffer.hasValue()) return; - } - std::unique_ptr &MB = *MBOrErr; - MemoryBufferRef MBRef = MB->getMemBufferRef(); - OwningMBs.push_back(std::move(MB)); // take MB ownership + MemoryBufferRef MBRef = *Buffer; switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: @@ -136,6 +133,23 @@ } } +llvm::Optional LinkerDriver::readFile(StringRef Path) { + auto MBOrErr = MemoryBuffer::getFile(Path); + if (std::error_code EC = MBOrErr.getError()) { + error(MBOrErr, "cannot open " + Path); + return None; + } + std::unique_ptr &MB = *MBOrErr; + MemoryBufferRef MBRef = MB->getMemBufferRef(); + OwningMBs.push_back(std::move(MB)); // take MB ownership + return MBRef; +} + +void LinkerDriver::readDynamicList(StringRef Path) { + if (llvm::Optional Buffer = readFile(Path)) + parseDynamicList(*Buffer); +} + // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { std::string Path = searchLibrary(Name); @@ -303,6 +317,8 @@ Config->OutputFile = getString(Args, OPT_o); Config->SoName = getString(Args, OPT_soname); Config->Sysroot = getString(Args, OPT_sysroot); + if (Args.hasArg(OPT_dynamic_list)) + 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,28 @@ +//===- 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; + +void parseDynamicList(MemoryBufferRef MB); + +} // namespace elf +} // namespace lld + +#endif Index: ELF/DynamicList.cpp =================================================================== --- /dev/null +++ ELF/DynamicList.cpp @@ -0,0 +1,68 @@ +//===- 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; + +// 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() override; + +private: + void readGroup(); +}; + +// Parse the default group definition using C language symbol name. +void DynamicListParser::readGroup() { + expect("{"); + while (!Error) { + Config->DynamicList.push_back(next()); + expect(";"); + if (peek() == "}") { + next(); + break; + } + } + expect(";"); +} + +void DynamicListParser::run() { + while (!atEOF()) + readGroup(); +} + +void elf::parseDynamicList(MemoryBufferRef MB) { + DynamicListParser(MB.getBuffer()).run(); +} Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -166,6 +166,9 @@ def z : JoinedOrSeparate<["-"], "z">, MetaVarName<"