forked from OSchip/llvm-project
[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
This commit is contained in:
parent
8adbded6a4
commit
2696bbeb93
|
@ -32,6 +32,7 @@ struct Configuration {
|
||||||
bool NoInhibitExec;
|
bool NoInhibitExec;
|
||||||
bool Shared;
|
bool Shared;
|
||||||
bool Static = false;
|
bool Static = false;
|
||||||
|
bool WholeArchive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Configuration *Config;
|
extern Configuration *Config;
|
||||||
|
|
|
@ -139,6 +139,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||||
case OPT_Bdynamic:
|
case OPT_Bdynamic:
|
||||||
Config->Static = false;
|
Config->Static = false;
|
||||||
break;
|
break;
|
||||||
|
case OPT_whole_archive:
|
||||||
|
Config->WholeArchive = true;
|
||||||
|
break;
|
||||||
|
case OPT_no_whole_archive:
|
||||||
|
Config->WholeArchive = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
ErrorOr<std::unique_ptr<Archive>> ArchiveOrErr = Archive::create(MB);
|
||||||
error(ArchiveOrErr, "Failed to parse archive");
|
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.
|
// Allocate a buffer for Lazy objects.
|
||||||
size_t NumSyms = File->getNumberOfSymbols();
|
size_t NumSyms = File->getNumberOfSymbols();
|
||||||
|
@ -211,6 +215,20 @@ MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
|
||||||
return *Ret;
|
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>
|
template <class ELFT>
|
||||||
SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
|
SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
|
||||||
: SharedFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}
|
: SharedFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}
|
||||||
|
|
|
@ -176,6 +176,7 @@ public:
|
||||||
MemoryBufferRef getMember(const Archive::Symbol *Sym);
|
MemoryBufferRef getMember(const Archive::Symbol *Sym);
|
||||||
|
|
||||||
llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
|
llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; }
|
||||||
|
std::vector<MemoryBufferRef> getMembers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Archive> File;
|
std::unique_ptr<Archive> File;
|
||||||
|
|
|
@ -37,6 +37,9 @@ def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
|
||||||
|
|
||||||
def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
|
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">,
|
def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
|
||||||
HelpText<"Retain the executable output file whenever it is still usable">;
|
HelpText<"Retain the executable output file whenever it is still usable">;
|
||||||
|
|
||||||
|
@ -52,6 +55,9 @@ def shared : Flag<["-"], "shared">,
|
||||||
def sysroot : Joined<["--"], "sysroot=">,
|
def sysroot : Joined<["--"], "sysroot=">,
|
||||||
HelpText<"Set the system root">;
|
HelpText<"Set the system root">;
|
||||||
|
|
||||||
|
def whole_archive : Flag<["--"], "whole-archive">,
|
||||||
|
HelpText<"Force load of all members in a static library">;
|
||||||
|
|
||||||
// Aliases
|
// Aliases
|
||||||
def alias_Bdynamic_call_shared: Flag<["-"], "call_shared">, Alias<Bdynamic>;
|
def alias_Bdynamic_call_shared: Flag<["-"], "call_shared">, Alias<Bdynamic>;
|
||||||
def alias_Bdynamic_dy: Flag<["-"], "dy">, Alias<Bdynamic>;
|
def alias_Bdynamic_dy: Flag<["-"], "dy">, Alias<Bdynamic>;
|
||||||
|
|
|
@ -28,15 +28,21 @@ bool SymbolTable::shouldUseRela() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
|
void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
|
||||||
File->parse();
|
if (auto *AF = dyn_cast<ArchiveFile>(File.get())) {
|
||||||
InputFile *FileP = File.release();
|
File.release();
|
||||||
if (auto *AF = dyn_cast<ArchiveFile>(FileP)) {
|
|
||||||
ArchiveFiles.emplace_back(AF);
|
ArchiveFiles.emplace_back(AF);
|
||||||
|
if (Config->WholeArchive) {
|
||||||
|
for (MemoryBufferRef &MBRef : AF->getMembers())
|
||||||
|
addFile(createELFFile<ObjectFile>(MBRef));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AF->parse();
|
||||||
for (Lazy &Sym : AF->getLazySymbols())
|
for (Lazy &Sym : AF->getLazySymbols())
|
||||||
addLazy(&Sym);
|
addLazy(&Sym);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addELFFile(cast<ELFFileBase>(FileP));
|
File->parse();
|
||||||
|
addELFFile(cast<ELFFileBase>(File.release()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static TargetInfo *createTarget(uint16_t EMachine) {
|
static TargetInfo *createTarget(uint16_t EMachine) {
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
.globl _bar;
|
||||||
|
_bar:
|
|
@ -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:
|
Loading…
Reference in New Issue