[lld] r266227 - ELF: Implement --dynamic-list
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 13 13:34:14 PDT 2016
This commit contains a few trailing whitespaces. Can you remove?
On Wed, Apr 13, 2016 at 11:51 AM, Adhemerval Zanella via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: azanella
> Date: Wed Apr 13 13:51:11 2016
> New Revision: 266227
>
> URL: http://llvm.org/viewvc/llvm-project?rev=266227&view=rev
> Log:
> ELF: Implement --dynamic-list
>
> This patch implements the --dynamic-list option, which adds a list of
> global symbol that either should not be bounded by default definition
> when creating shared libraries, or add in dynamic symbol table in the
> case of creating executables.
>
> The patch modifies the ScriptParserBase class to use a list of Token
> instead of StringRef, which contains information if the token is a
> quoted or unquoted strings. It is used to use a faster search for
> exact match symbol name.
>
> The input file follow a similar format of linker script with some
> simplifications (it does not have scope or node names). It leads
> to a simplified parser define in DynamicList.{cpp,h}.
>
> Different from ld/gold neither glob pattern nor mangled names
> (extern 'C++') are currently supported.
>
> Added:
> lld/trunk/ELF/DynamicList.cpp
> lld/trunk/ELF/DynamicList.h
> lld/trunk/test/ELF/dynamic-list.s
> lld/trunk/test/ELF/invalid-dynamic-list.test
> Modified:
> lld/trunk/ELF/CMakeLists.txt
> lld/trunk/ELF/Config.h
> lld/trunk/ELF/Driver.cpp
> lld/trunk/ELF/Driver.h
> lld/trunk/ELF/Options.td
> lld/trunk/ELF/SymbolTable.cpp
> lld/trunk/ELF/SymbolTable.h
>
> Modified: lld/trunk/ELF/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=266227&r1=266226&r2=266227&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/CMakeLists.txt (original)
> +++ lld/trunk/ELF/CMakeLists.txt Wed Apr 13 13:51:11 2016
> @@ -5,6 +5,7 @@ add_public_tablegen_target(ELFOptionsTab
> add_lld_library(lldELF
> Driver.cpp
> DriverUtils.cpp
> + DynamicList.cpp
> Error.cpp
> ICF.cpp
> InputFiles.cpp
>
> Modified: lld/trunk/ELF/Config.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=266227&r1=266226&r2=266227&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Config.h (original)
> +++ lld/trunk/ELF/Config.h Wed Apr 13 13:51:11 2016
> @@ -48,6 +48,7 @@ struct Configuration {
> llvm::StringRef SoName;
> llvm::StringRef Sysroot;
> std::string RPath;
> + std::vector<llvm::StringRef> DynamicList;
> std::vector<llvm::StringRef> SearchPaths;
> std::vector<llvm::StringRef> Undefined;
> bool AllowMultipleDefinition;
>
> Modified: lld/trunk/ELF/Driver.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=266227&r1=266226&r2=266227&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Driver.cpp (original)
> +++ lld/trunk/ELF/Driver.cpp Wed Apr 13 13:51:11 2016
> @@ -8,6 +8,7 @@
>
> //===----------------------------------------------------------------------===//
>
> #include "Driver.h"
> +#include "DynamicList.h"
> #include "Config.h"
> #include "Error.h"
> #include "ICF.h"
> @@ -100,14 +101,10 @@ void LinkerDriver::addFile(StringRef Pat
> using namespace llvm::sys::fs;
> if (Config->Verbose)
> llvm::outs() << Path << "\n";
> - auto MBOrErr = MemoryBuffer::getFile(Path);
> - if (!MBOrErr) {
> - error(MBOrErr, "cannot open " + Path);
> + Optional<MemoryBufferRef> Buffer = readFile(Path);
> + if (!Buffer.hasValue())
> return;
> - }
> - std::unique_ptr<MemoryBuffer> &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 @@ void LinkerDriver::addFile(StringRef Pat
> }
> }
>
> +Optional<MemoryBufferRef> 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<MemoryBuffer> &MB = *MBOrErr;
> + MemoryBufferRef MBRef = MB->getMemBufferRef();
> + OwningMBs.push_back(std::move(MB)); // take MB ownership
> + return MBRef;
> +}
> +
> +void LinkerDriver::readDynamicList(StringRef Path) {
> + if (Optional<MemoryBufferRef> 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);
> @@ -351,6 +365,9 @@ void LinkerDriver::readConfigs(opt::Inpu
>
> for (auto *Arg : Args.filtered(OPT_undefined))
> Config->Undefined.push_back(Arg->getValue());
> +
> + if (Args.hasArg(OPT_dynamic_list))
> + readDynamicList(getString(Args, OPT_dynamic_list));
> }
>
> void LinkerDriver::createFiles(opt::InputArgList &Args) {
> @@ -437,6 +454,7 @@ template <class ELFT> void LinkerDriver:
>
> // Write the result to the file.
> Symtab.scanShlibUndefined();
> + Symtab.scanDynamicList();
> if (Config->GcSections)
> markLive<ELFT>(&Symtab);
> if (Config->ICF)
>
> Modified: lld/trunk/ELF/Driver.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.h?rev=266227&r1=266226&r2=266227&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Driver.h (original)
> +++ lld/trunk/ELF/Driver.h Wed Apr 13 13:51:11 2016
> @@ -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 @@ public:
>
> private:
> std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
> + llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
> void readConfigs(llvm::opt::InputArgList &Args);
> + void readDynamicList(StringRef Path);
> void createFiles(llvm::opt::InputArgList &Args);
> template <class ELFT> void link(llvm::opt::InputArgList &Args);
>
>
> Added: lld/trunk/ELF/DynamicList.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/DynamicList.cpp?rev=266227&view=auto
>
> ==============================================================================
> --- lld/trunk/ELF/DynamicList.cpp (added)
> +++ lld/trunk/ELF/DynamicList.cpp Wed Apr 13 13:51:11 2016
> @@ -0,0 +1,64 @@
> +//===- 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 "ScriptParser.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/Path.h"
> +
> +using namespace llvm;
> +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 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();
> +}
>
> Added: lld/trunk/ELF/DynamicList.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/DynamicList.h?rev=266227&view=auto
>
> ==============================================================================
> --- lld/trunk/ELF/DynamicList.h (added)
> +++ lld/trunk/ELF/DynamicList.h Wed Apr 13 13:51:11 2016
> @@ -0,0 +1,24 @@
> +//===- 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/Support/MemoryBuffer.h"
> +
> +namespace lld {
> +namespace elf {
> +
> +void parseDynamicList(MemoryBufferRef MB);
> +
> +} // namespace elf
> +} // namespace lld
> +
> +#endif
>
> Modified: lld/trunk/ELF/Options.td
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=266227&r1=266226&r2=266227&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Options.td (original)
> +++ lld/trunk/ELF/Options.td Wed Apr 13 13:51:11 2016
> @@ -44,6 +44,9 @@ def discard_none : Flag<["-"], "discard-
> def dynamic_linker : Separate<["--", "-"], "dynamic-linker">,
> HelpText<"Which dynamic linker to use">;
>
> +def dynamic_list : Separate<["--", "-"], "dynamic-list">,
> + HelpText<"Read a list of dynamic symbols">;
> +
> def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">,
> HelpText<"Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME
> segment header">;
>
> @@ -175,6 +178,7 @@ def alias_Bstatic_static: Flag<["-"], "s
> def alias_L__library_path : Joined<["--"], "library-path=">, Alias<L>;
> def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
> def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
> +def alias_dynamic_list: Joined<["--", "-"], "dynamic-list=">,
> Alias<dynamic_list>;
> def alias_entry_e : JoinedOrSeparate<["-"], "e">, Alias<entry>;
> def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>;
> def alias_fini_fini : Joined<["-"], "fini=">, Alias<fini>;
>
> Modified: lld/trunk/ELF/SymbolTable.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=266227&r1=266226&r2=266227&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/SymbolTable.cpp (original)
> +++ lld/trunk/ELF/SymbolTable.cpp Wed Apr 13 13:51:11 2016
> @@ -339,6 +339,14 @@ template <class ELFT> void SymbolTable<E
> Sym->MustBeInDynSym = true;
> }
>
> +// This function process the dynamic list option by marking all the
> symbols
> +// to be exported in the dynamic table.
> +template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
> + for (StringRef S : Config->DynamicList)
> + if (SymbolBody *B = find(S))
> + B->MustBeInDynSym = true;
> +}
> +
> template class elf::SymbolTable<ELF32LE>;
> template class elf::SymbolTable<ELF32BE>;
> template class elf::SymbolTable<ELF64LE>;
>
> Modified: lld/trunk/ELF/SymbolTable.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=266227&r1=266226&r2=266227&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/SymbolTable.h (original)
> +++ lld/trunk/ELF/SymbolTable.h Wed Apr 13 13:51:11 2016
> @@ -60,6 +60,7 @@ public:
> uint8_t Visibility =
> llvm::ELF::STV_HIDDEN);
>
> void scanShlibUndefined();
> + void scanDynamicList();
> SymbolBody *find(StringRef Name);
> void wrap(StringRef Name);
> InputFile *findFile(SymbolBody *B);
>
> Added: lld/trunk/test/ELF/dynamic-list.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/dynamic-list.s?rev=266227&view=auto
>
> ==============================================================================
> --- lld/trunk/test/ELF/dynamic-list.s (added)
> +++ lld/trunk/test/ELF/dynamic-list.s Wed Apr 13 13:51:11 2016
> @@ -0,0 +1,104 @@
> +## There is some bad quoting interaction between lit's internal shell,
> which is
> +## implemented in Python, and the Cygwin implementations of the Unix
> utilities.
> +## Avoid running these tests on Windows for now by requiring a real shell.
> +
> +# REQUIRES: shell
> +
> +# REQUIRES: x86
> +
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux
> %p/Inputs/shared.s -o %t2.o
> +# RUN: ld.lld -shared %t2.o -soname shared -o %t2.so
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
> +
> +## Check exporting only one symbol.
> +# RUN: echo "{ foo1; };" > %t.list
> +# RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe
> +# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s
> +
> +## And now using quoted strings (the output is the same since it does
> +## use any wildcard character).
> +# RUN: echo "{ \"foo1\"; };" > %t.list
> +# RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe
> +# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s
> +
> +# CHECK: DynamicSymbols [
> +# CHECK-NEXT: Symbol {
> +# CHECK-NEXT: Name: @ (0)
> +# CHECK-NEXT: Value: 0x0
> +# CHECK-NEXT: Size: 0
> +# CHECK-NEXT: Binding: Local
> +# CHECK-NEXT: Type: None
> +# CHECK-NEXT: Other: 0
> +# CHECK-NEXT: Section: Undefined
> +# CHECK-NEXT: }
> +# CHECK-NEXT: Symbol {
> +# CHECK-NEXT: Name: foo1@ (1)
> +# CHECK-NEXT: Value: 0x11000
> +# CHECK-NEXT: Size: 0
> +# CHECK-NEXT: Binding: Global (0x1)
> +# CHECK-NEXT: Type: None (0x0)
> +# CHECK-NEXT: Other: 0
> +# CHECK-NEXT: Section: .text (0x4)
> +# CHECK-NEXT: }
> +# CHECK-NEXT: ]
> +
> +
> +## Now export all the foo1, foo2, and foo31 symbols
> +# RUN: echo "{ foo1; foo2; foo31; };" > %t.list
> +# RUN: ld.lld --dynamic-list %t.list %t %t2.so -o %t.exe
> +# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2
> %s
> +
> +# CHECK2: DynamicSymbols [
> +# CHECK2-NEXT: Symbol {
> +# CHECK2-NEXT: Name: @ (0)
> +# CHECK2-NEXT: Value: 0x0
> +# CHECK2-NEXT: Size: 0
> +# CHECK2-NEXT: Binding: Local
> +# CHECK2-NEXT: Type: None
> +# CHECK2-NEXT: Other: 0
> +# CHECK2-NEXT: Section: Undefined
> +# CHECK2-NEXT: }
> +# CHECK2-NEXT: Symbol {
> +# CHECK2-NEXT: Name: foo1@ (1)
> +# CHECK2-NEXT: Value: 0x11000
> +# CHECK2-NEXT: Size: 0
> +# CHECK2-NEXT: Binding: Global (0x1)
> +# CHECK2-NEXT: Type: None (0x0)
> +# CHECK2-NEXT: Other: 0
> +# CHECK2-NEXT: Section: .text (0x4)
> +# CHECK2-NEXT: }
> +# CHECK2-NEXT: Symbol {
> +# CHECK2-NEXT: Name: foo2@ (6)
> +# CHECK2-NEXT: Value: 0x11001
> +# CHECK2-NEXT: Size: 0
> +# CHECK2-NEXT: Binding: Global (0x1)
> +# CHECK2-NEXT: Type: None (0x0)
> +# CHECK2-NEXT: Other: 0
> +# CHECK2-NEXT: Section: .text (0x4)
> +# CHECK2-NEXT: }
> +# CHECK2-NEXT: Symbol {
> +# CHECK2-NEXT: Name: foo31@ (11)
> +# CHECK2-NEXT: Value: 0x11002
> +# CHECK2-NEXT: Size: 0
> +# CHECK2-NEXT: Binding: Global (0x1)
> +# CHECK2-NEXT: Type: None (0x0)
> +# CHECK2-NEXT: Other: 0
> +# CHECK2-NEXT: Section: .text (0x4)
> +# CHECK2-NEXT: }
> +# CHECK2-NEXT: ]
> +
> +.globl foo1
> +foo1:
> + ret
> +
> +.globl foo2
> +foo2:
> + ret
> +
> +.globl foo31
> +foo31:
> + ret
> +
> +.globl _start
> +_start:
> + retq
>
> Added: lld/trunk/test/ELF/invalid-dynamic-list.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid-dynamic-list.test?rev=266227&view=auto
>
> ==============================================================================
> --- lld/trunk/test/ELF/invalid-dynamic-list.test (added)
> +++ lld/trunk/test/ELF/invalid-dynamic-list.test Wed Apr 13 13:51:11 2016
> @@ -0,0 +1,37 @@
> +## Different "echo" commands on Windows interpret quoted strings and
> +## wildcards in similar but different way (On Windows, ARGV tokenization
> +## and wildcard expansion are not done by the shell but by each command.)
> +## Because of that reason, this test fails on some Windows environment.
> +## We can't write quoted strings that are interpreted the same way
> +## by all echo commands. So, we don't want to run this on Windows.
> +
> +# REQUIRES: shell
> +
> +# RUN: mkdir -p %t.dir
> +
> +# RUN: echo foobar > %t1
> +# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR1
> %s
> +# ERR1: line 1: { expected, but got foobar
> +
> +# RUN: echo "{ foobar;" > %t1
> +# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR2
> %s
> +# ERR2: line 1: unexpected EOF
> +
> +## Missing ';' before '}'
> +# RUN: echo "{ foobar }" > %t1
> +# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR3
> %s
> +# ERR3: line 1: ; expected, but got }
> +
> +## Missing final ';'
> +# RUN: echo "{ foobar; }" > %t1
> +# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR4
> %s
> +# ERR4: line 1: unexpected EOF
> +
> +## Missing \" in foobar definition
> +# RUN echo "{ \"foobar; };" > %t1
> +# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR5
> %s
> +# ERR5: line 1: unexpected EOF
> +
> +# RUN: echo "{ extern \"BOGUS\" { test }; };" > %t1
> +# RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR6
> %s
> +# ERR6: line 1: ; expected, but got BOGUS
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160413/5aae6af9/attachment.html>
More information about the llvm-commits
mailing list