summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp6
-rw-r--r--lld/ELF/InputFiles.cpp22
-rw-r--r--lld/ELF/InputFiles.h1
-rw-r--r--lld/ELF/Options.td6
-rw-r--r--lld/ELF/SymbolTable.cpp14
-rw-r--r--lld/test/elf2/Inputs/whole-archive.s2
-rw-r--r--lld/test/elf2/whole-archive.s34
8 files changed, 80 insertions, 6 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 10b92b7c19b..2e2c031abbb 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -32,6 +32,7 @@ struct Configuration {
bool NoInhibitExec;
bool Shared;
bool Static = false;
+ bool WholeArchive = false;
};
extern Configuration *Config;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index e611511d64f..af8144fbd98 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -139,6 +139,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
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;
}
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index cc7bbaa9216..5eabb298c2a 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -181,10 +181,14 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
}
}
-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(const Archive::Symbol *Sym) {
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) {}
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 47bf36fe5b9..4bb0d8f8ca5 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -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;
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 8b8e265d7df..4d4a84eee6c 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -37,6 +37,9 @@ def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
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>;
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 43b068d6676..42b04596b89 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -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) {
diff --git a/lld/test/elf2/Inputs/whole-archive.s b/lld/test/elf2/Inputs/whole-archive.s
new file mode 100644
index 00000000000..f9d56fc2fa2
--- /dev/null
+++ b/lld/test/elf2/Inputs/whole-archive.s
@@ -0,0 +1,2 @@
+.globl _bar;
+_bar:
diff --git a/lld/test/elf2/whole-archive.s b/lld/test/elf2/whole-archive.s
new file mode 100644
index 00000000000..0b14ada126c
--- /dev/null
+++ b/lld/test/elf2/whole-archive.s
@@ -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:
OpenPOWER on IntegriCloud