forked from OSchip/llvm-project
[lld] Fix --exclude-libs broken when --whole-archive is used
Summary: **Problem** `--exclude-libs` does not work for static libraries affected by the `--whole-archive` option. **Description** `--exclude-libs` creates a list of static library paths and does library lookups in this list. `--whole-archive` splits the static libraries that follow it into separate objects. As a result, lld no longer sees static libraries among linked files and does no `--exclude-libs` lookups. **Solution** The proposed solution is to make `--exclude-libs` consider object files too. When lld finds an object file it checks whether this file originates from an archive and, if so, looks the archive up in the `--exclude-libs` list. Reviewers: ruiu, rafael Reviewed By: ruiu Subscribers: asl, ikudrin, llvm-commits, emaste Tags: #lld Differential Revision: https://reviews.llvm.org/D39353 llvm-svn: 316998
This commit is contained in:
parent
f753bfeeec
commit
0cf24ed9aa
|
@ -978,21 +978,32 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) {
|
|||
return Ret;
|
||||
}
|
||||
|
||||
static Optional<StringRef> getArchiveName(InputFile *File) {
|
||||
if (isa<ArchiveFile>(File))
|
||||
return File->getName();
|
||||
if (!File->ArchiveName.empty())
|
||||
return File->ArchiveName;
|
||||
return None;
|
||||
}
|
||||
|
||||
// Handles the -exclude-libs option. If a static library file is specified
|
||||
// by the -exclude-libs option, all public symbols from the archive become
|
||||
// private unless otherwise specified by version scripts or something.
|
||||
// A special library name "ALL" means all archive files.
|
||||
//
|
||||
// This is not a popular option, but some programs such as bionic libc use it.
|
||||
template <class ELFT>
|
||||
static void excludeLibs(opt::InputArgList &Args, ArrayRef<InputFile *> Files) {
|
||||
DenseSet<StringRef> Libs = getExcludeLibs(Args);
|
||||
bool All = Libs.count("ALL");
|
||||
|
||||
for (InputFile *File : Files)
|
||||
if (auto *F = dyn_cast<ArchiveFile>(File))
|
||||
if (All || Libs.count(path::filename(F->getName())))
|
||||
for (SymbolBody *Sym : F->getSymbols())
|
||||
Sym->symbol()->VersionId = VER_NDX_LOCAL;
|
||||
for (InputFile *File : Files) {
|
||||
if (Optional<StringRef> Archive = getArchiveName(File))
|
||||
if (All || Libs.count(path::filename(*Archive)))
|
||||
for (SymbolBody *SymBody : File->getSymbols())
|
||||
if (!SymBody->isLocal())
|
||||
SymBody->symbol()->VersionId = VER_NDX_LOCAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Do actual linking. Note that when this function is called,
|
||||
|
@ -1075,7 +1086,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
|
||||
// Handle the -exclude-libs option.
|
||||
if (Args.hasArg(OPT_exclude_libs))
|
||||
excludeLibs(Args, Files);
|
||||
excludeLibs<ELFT>(Args, Files);
|
||||
|
||||
// Apply version scripts.
|
||||
Symtab->scanVersionScript();
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL
|
||||
// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s
|
||||
|
||||
// RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo,bar,exc.a
|
||||
// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s
|
||||
|
||||
// RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL
|
||||
// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s
|
||||
|
||||
// DEFAULT: Name: fn
|
||||
// EXCLUDE-NOT: Name: fn
|
||||
|
||||
|
|
Loading…
Reference in New Issue