Skip to content

Commit 2696bbe

Browse files
author
Igor Kudrin
committedOct 1, 2015
[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 llvm-svn: 249045
1 parent 8adbded commit 2696bbe

File tree

8 files changed

+80
-6
lines changed

8 files changed

+80
-6
lines changed
 

‎lld/ELF/Config.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct Configuration {
3232
bool NoInhibitExec;
3333
bool Shared;
3434
bool Static = false;
35+
bool WholeArchive = false;
3536
};
3637

3738
extern Configuration *Config;

‎lld/ELF/Driver.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
139139
case OPT_Bdynamic:
140140
Config->Static = false;
141141
break;
142+
case OPT_whole_archive:
143+
Config->WholeArchive = true;
144+
break;
145+
case OPT_no_whole_archive:
146+
Config->WholeArchive = false;
147+
break;
142148
default:
143149
break;
144150
}

‎lld/ELF/InputFiles.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,14 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
181181
}
182182
}
183183

184-
void ArchiveFile::parse() {
184+
static std::unique_ptr<Archive> openArchive(MemoryBufferRef MB) {
185185
ErrorOr<std::unique_ptr<Archive>> ArchiveOrErr = Archive::create(MB);
186186
error(ArchiveOrErr, "Failed to parse archive");
187-
File = std::move(*ArchiveOrErr);
187+
return std::move(*ArchiveOrErr);
188+
}
189+
190+
void ArchiveFile::parse() {
191+
File = openArchive(MB);
188192

189193
// Allocate a buffer for Lazy objects.
190194
size_t NumSyms = File->getNumberOfSymbols();
@@ -211,6 +215,20 @@ MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
211215
return *Ret;
212216
}
213217

218+
std::vector<MemoryBufferRef> ArchiveFile::getMembers() {
219+
File = openArchive(MB);
220+
221+
std::vector<MemoryBufferRef> Result;
222+
for (const Archive::Child &Child : File->children()) {
223+
ErrorOr<MemoryBufferRef> MbOrErr = Child.getMemoryBufferRef();
224+
error(MbOrErr,
225+
Twine("Could not get the buffer for a child of the archive ") +
226+
File->getFileName());
227+
Result.push_back(MbOrErr.get());
228+
}
229+
return Result;
230+
}
231+
214232
template <class ELFT>
215233
SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
216234
: SharedFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}

‎lld/ELF/InputFiles.h

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class ArchiveFile : public InputFile {
176176
MemoryBufferRef getMember(const Archive::Symbol *Sym);
177177

178178
llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
179+
std::vector<MemoryBufferRef> getMembers();
179180

180181
private:
181182
std::unique_ptr<Archive> File;

‎lld/ELF/Options.td

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
3737

3838
def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
3939

40+
def no_whole_archive : Flag<["--"], "no-whole-archive">,
41+
HelpText<"Restores the default behavior of loading archive members">;
42+
4043
def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
4144
HelpText<"Retain the executable output file whenever it is still usable">;
4245

@@ -52,6 +55,9 @@ def shared : Flag<["-"], "shared">,
5255
def sysroot : Joined<["--"], "sysroot=">,
5356
HelpText<"Set the system root">;
5457

58+
def whole_archive : Flag<["--"], "whole-archive">,
59+
HelpText<"Force load of all members in a static library">;
60+
5561
// Aliases
5662
def alias_Bdynamic_call_shared: Flag<["-"], "call_shared">, Alias<Bdynamic>;
5763
def alias_Bdynamic_dy: Flag<["-"], "dy">, Alias<Bdynamic>;

‎lld/ELF/SymbolTable.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,21 @@ bool SymbolTable::shouldUseRela() const {
2828
}
2929

3030
void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
31-
File->parse();
32-
InputFile *FileP = File.release();
33-
if (auto *AF = dyn_cast<ArchiveFile>(FileP)) {
31+
if (auto *AF = dyn_cast<ArchiveFile>(File.get())) {
32+
File.release();
3433
ArchiveFiles.emplace_back(AF);
34+
if (Config->WholeArchive) {
35+
for (MemoryBufferRef &MBRef : AF->getMembers())
36+
addFile(createELFFile<ObjectFile>(MBRef));
37+
return;
38+
}
39+
AF->parse();
3540
for (Lazy &Sym : AF->getLazySymbols())
3641
addLazy(&Sym);
3742
return;
3843
}
39-
addELFFile(cast<ELFFileBase>(FileP));
44+
File->parse();
45+
addELFFile(cast<ELFFileBase>(File.release()));
4046
}
4147

4248
static TargetInfo *createTarget(uint16_t EMachine) {

‎lld/test/elf2/Inputs/whole-archive.s

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.globl _bar;
2+
_bar:

‎lld/test/elf2/whole-archive.s

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// REQUIRES: x86
2+
3+
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4+
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
5+
// RUN: %p/Inputs/whole-archive.s -o %ta.o
6+
// RUN: rm -f %t.a
7+
// RUN: llvm-ar rcs %t.a %ta.o
8+
9+
// Should not add symbols from the archive by default as they are not required
10+
// RUN: lld -flavor gnu2 -o %t3 %t.o %t.a
11+
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
12+
// NOTADDED: Symbols [
13+
// NOTADDED-NOT: Name: _bar
14+
// NOTADDED: ]
15+
16+
// Should add symbols from the archive if --whole-archive is used
17+
// RUN: lld -flavor gnu2 -o %t3 %t.o --whole-archive %t.a
18+
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=ADDED %s
19+
// ADDED: Symbols [
20+
// ADDED: Name: _bar
21+
// ADDED: ]
22+
23+
// --no-whole-archive should restore default behaviour
24+
// RUN: lld -flavor gnu2 -o %t3 %t.o --whole-archive --no-whole-archive %t.a
25+
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
26+
27+
// --whole-archive and --no-whole-archive should affect only archives which follow them
28+
// RUN: lld -flavor gnu2 -o %t3 %t.o %t.a --whole-archive --no-whole-archive
29+
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
30+
// RUN: lld -flavor gnu2 -o %t3 %t.o --whole-archive %t.a --no-whole-archive
31+
// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=ADDED %s
32+
33+
.globl _start;
34+
_start:

0 commit comments

Comments
 (0)
Please sign in to comment.