[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