[lld] r249045 - [ELF2] Add --[no-]whole-archive command line switches

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 11:02:22 PDT 2015


Author: ikudrin
Date: Thu Oct  1 13:02:21 2015
New Revision: 249045

URL: http://llvm.org/viewvc/llvm-project?rev=249045&view=rev
Log:
[ELF2] Add --[no-]whole-archive command line switches

Summary:
If --whole-archive is used, all symbols from the following archives are added to the output. --no-whole-archive restores default behavior. These switches can be used multiple times.

NB. We have to keep an ArchiveFile instance within SymbolTable even if --whole-archive mode is active since it can be a thin archive which contains just names of external files. In that case actual memory buffers for the archive members will be stored within the File member of ArchiveFile class.

Reviewers: rafael, ruiu

Subscribers: grimar, llvm-commits

Projects: #lld

Differential Revision: http://reviews.llvm.org/D13286

Added:
    lld/trunk/test/elf2/Inputs/whole-archive.s
    lld/trunk/test/elf2/whole-archive.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/SymbolTable.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=249045&r1=249044&r2=249045&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Thu Oct  1 13:02:21 2015
@@ -32,6 +32,7 @@ struct Configuration {
   bool NoInhibitExec;
   bool Shared;
   bool Static = false;
+  bool WholeArchive = false;
 };
 
 extern Configuration *Config;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249045&r1=249044&r2=249045&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu Oct  1 13:02:21 2015
@@ -139,6 +139,12 @@ void LinkerDriver::link(ArrayRef<const c
     case OPT_Bdynamic:
       Config->Static = false;
       break;
+    case OPT_whole_archive:
+      Config->WholeArchive = true;
+      break;
+    case OPT_no_whole_archive:
+      Config->WholeArchive = false;
+      break;
     default:
       break;
     }

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=249045&r1=249044&r2=249045&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Thu Oct  1 13:02:21 2015
@@ -181,10 +181,14 @@ SymbolBody *elf2::ObjectFile<ELFT>::crea
   }
 }
 
-void ArchiveFile::parse() {
+static std::unique_ptr<Archive> openArchive(MemoryBufferRef MB) {
   ErrorOr<std::unique_ptr<Archive>> ArchiveOrErr = Archive::create(MB);
   error(ArchiveOrErr, "Failed to parse archive");
-  File = std::move(*ArchiveOrErr);
+  return std::move(*ArchiveOrErr);
+}
+
+void ArchiveFile::parse() {
+  File = openArchive(MB);
 
   // Allocate a buffer for Lazy objects.
   size_t NumSyms = File->getNumberOfSymbols();
@@ -211,6 +215,20 @@ MemoryBufferRef ArchiveFile::getMember(c
   return *Ret;
 }
 
+std::vector<MemoryBufferRef> ArchiveFile::getMembers() {
+  File = openArchive(MB);
+
+  std::vector<MemoryBufferRef> Result;
+  for (const Archive::Child &Child : File->children()) {
+    ErrorOr<MemoryBufferRef> MbOrErr = Child.getMemoryBufferRef();
+    error(MbOrErr,
+          Twine("Could not get the buffer for a child of the archive ") +
+              File->getFileName());
+    Result.push_back(MbOrErr.get());
+  }
+  return Result;
+}
+
 template <class ELFT>
 SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
     : SharedFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=249045&r1=249044&r2=249045&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Thu Oct  1 13:02:21 2015
@@ -176,6 +176,7 @@ public:
   MemoryBufferRef getMember(const Archive::Symbol *Sym);
 
   llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
+  std::vector<MemoryBufferRef> getMembers();
 
 private:
   std::unique_ptr<Archive> File;

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=249045&r1=249044&r2=249045&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Thu Oct  1 13:02:21 2015
@@ -37,6 +37,9 @@ def l : Joined<["-"], "l">, MetaVarName<
 
 def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
 
+def no_whole_archive : Flag<["--"], "no-whole-archive">,
+  HelpText<"Restores the default behavior of loading archive members">;
+
 def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
   HelpText<"Retain the executable output file whenever it is still usable">;
 
@@ -52,6 +55,9 @@ def shared : Flag<["-"], "shared">,
 def sysroot : Joined<["--"], "sysroot=">,
   HelpText<"Set the system root">;
 
+def whole_archive : Flag<["--"], "whole-archive">,
+  HelpText<"Force load of all members in a static library">;
+
 // Aliases
 def alias_Bdynamic_call_shared: Flag<["-"], "call_shared">, Alias<Bdynamic>;
 def alias_Bdynamic_dy: Flag<["-"], "dy">, Alias<Bdynamic>;

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=249045&r1=249044&r2=249045&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Thu Oct  1 13:02:21 2015
@@ -28,15 +28,21 @@ bool SymbolTable::shouldUseRela() const
 }
 
 void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
-  File->parse();
-  InputFile *FileP = File.release();
-  if (auto *AF = dyn_cast<ArchiveFile>(FileP)) {
+  if (auto *AF = dyn_cast<ArchiveFile>(File.get())) {
+    File.release();
     ArchiveFiles.emplace_back(AF);
+    if (Config->WholeArchive) {
+      for (MemoryBufferRef &MBRef : AF->getMembers())
+        addFile(createELFFile<ObjectFile>(MBRef));
+      return;
+    }
+    AF->parse();
     for (Lazy &Sym : AF->getLazySymbols())
       addLazy(&Sym);
     return;
   }
-  addELFFile(cast<ELFFileBase>(FileP));
+  File->parse();
+  addELFFile(cast<ELFFileBase>(File.release()));
 }
 
 static TargetInfo *createTarget(uint16_t EMachine) {

Added: lld/trunk/test/elf2/Inputs/whole-archive.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/whole-archive.s?rev=249045&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/whole-archive.s (added)
+++ lld/trunk/test/elf2/Inputs/whole-archive.s Thu Oct  1 13:02:21 2015
@@ -0,0 +1,2 @@
+.globl _bar;
+_bar:

Added: lld/trunk/test/elf2/whole-archive.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/whole-archive.s?rev=249045&view=auto
==============================================================================
--- lld/trunk/test/elf2/whole-archive.s (added)
+++ lld/trunk/test/elf2/whole-archive.s Thu Oct  1 13:02:21 2015
@@ -0,0 +1,34 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN:   %p/Inputs/whole-archive.s -o %ta.o
+// RUN: rm -f %t.a
+// RUN: llvm-ar rcs %t.a %ta.o
+
+// Should not add symbols from the archive by default as they are not required
+// RUN: lld -flavor gnu2 -o %t3 %t.o %t.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
+// NOTADDED: Symbols [
+// NOTADDED-NOT: Name: _bar
+// NOTADDED: ]
+
+// Should add symbols from the archive if --whole-archive is used
+// RUN: lld -flavor gnu2 -o %t3 %t.o --whole-archive %t.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=ADDED %s
+// ADDED: Symbols [
+// ADDED: Name: _bar
+// ADDED: ]
+
+// --no-whole-archive should restore default behaviour
+// RUN: lld -flavor gnu2 -o %t3 %t.o --whole-archive --no-whole-archive %t.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
+
+// --whole-archive and --no-whole-archive should affect only archives which follow them
+// RUN: lld -flavor gnu2 -o %t3 %t.o %t.a --whole-archive --no-whole-archive
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
+// RUN: lld -flavor gnu2 -o %t3 %t.o --whole-archive %t.a --no-whole-archive
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=ADDED %s
+
+.globl _start;
+_start:




More information about the llvm-commits mailing list