forked from OSchip/llvm-project
Implement the --exclude-libs option.
The --exclude-libs option is not a popular option, but at least some programs in Android depend on it, so it's worth to support it. Differential Revision: https://reviews.llvm.org/D34422 llvm-svn: 305920
This commit is contained in:
parent
8f9621ae04
commit
d1f8b8162b
|
@ -908,6 +908,41 @@ getDefsym(opt::InputArgList &Args) {
|
|||
return Ret;
|
||||
}
|
||||
|
||||
// Parses `--exclude-libs=lib,lib,...`.
|
||||
// The library names may be delimited by commas or colons.
|
||||
static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) {
|
||||
DenseSet<StringRef> Ret;
|
||||
for (auto *Arg : Args.filtered(OPT_exclude_libs)) {
|
||||
StringRef S = Arg->getValue();
|
||||
for (;;) {
|
||||
size_t Pos = S.find_first_of(",:");
|
||||
if (Pos == StringRef::npos)
|
||||
break;
|
||||
Ret.insert(S.substr(0, Pos));
|
||||
S = S.substr(Pos + 1);
|
||||
}
|
||||
Ret.insert(S);
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
// 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.
|
||||
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 (Symbol *Sym : F->getSymbols())
|
||||
Sym->VersionId = VER_NDX_LOCAL;
|
||||
}
|
||||
|
||||
// Do actual linking. Note that when this function is called,
|
||||
// all linker scripts have already been parsed.
|
||||
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
|
@ -959,8 +994,17 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
if (ErrorCount)
|
||||
return;
|
||||
|
||||
// Handle the `--undefined <sym>` options.
|
||||
Symtab.scanUndefinedFlags();
|
||||
|
||||
// Handle undefined symbols in DSOs.
|
||||
Symtab.scanShlibUndefined();
|
||||
|
||||
// Handle the -exclude-libs option.
|
||||
if (Args.hasArg(OPT_exclude_libs))
|
||||
excludeLibs(Args, Files);
|
||||
|
||||
// Apply version scripts.
|
||||
Symtab.scanVersionScript();
|
||||
|
||||
// Create wrapped symbols for -wrap option.
|
||||
|
|
|
@ -632,8 +632,9 @@ ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File)
|
|||
File(std::move(File)) {}
|
||||
|
||||
template <class ELFT> void ArchiveFile::parse() {
|
||||
Symbols.reserve(File->getNumberOfSymbols());
|
||||
for (const Archive::Symbol &Sym : File->symbols())
|
||||
Symtab<ELFT>::X->addLazyArchive(this, Sym);
|
||||
Symbols.push_back(Symtab<ELFT>::X->addLazyArchive(this, Sym));
|
||||
}
|
||||
|
||||
// Returns a buffer pointing to a member file containing a given symbol.
|
||||
|
|
|
@ -251,6 +251,7 @@ public:
|
|||
explicit ArchiveFile(std::unique_ptr<Archive> &&File);
|
||||
static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
|
||||
template <class ELFT> void parse();
|
||||
ArrayRef<Symbol *> getSymbols() { return Symbols; }
|
||||
|
||||
// Returns a memory buffer for a given symbol and the offset in the archive
|
||||
// for the member. An empty memory buffer and an offset of zero
|
||||
|
@ -261,6 +262,7 @@ public:
|
|||
private:
|
||||
std::unique_ptr<Archive> File;
|
||||
llvm::DenseSet<uint64_t> Seen;
|
||||
std::vector<Symbol *> Symbols;
|
||||
};
|
||||
|
||||
class BitcodeFile : public InputFile {
|
||||
|
|
|
@ -92,6 +92,9 @@ def error_limit: S<"error-limit">,
|
|||
def error_unresolved_symbols: F<"error-unresolved-symbols">,
|
||||
HelpText<"Report unresolved symbols as errors">;
|
||||
|
||||
def exclude_libs: S<"exclude-libs">,
|
||||
HelpText<"Exclude static libraries from automatic export">;
|
||||
|
||||
def export_dynamic: F<"export-dynamic">,
|
||||
HelpText<"Put symbols in the dynamic symbol table">;
|
||||
|
||||
|
@ -298,6 +301,7 @@ def alias_emit_relocs: Flag<["-"], "q">, Alias<emit_relocs>;
|
|||
def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;
|
||||
def alias_entry_entry: J<"entry=">, Alias<entry>;
|
||||
def alias_error_limit: J<"error-limit=">, Alias<error_limit>;
|
||||
def alias_exclude_libs: J<"exclude-libs=">, Alias<exclude_libs>;
|
||||
def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>;
|
||||
def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">,
|
||||
Alias<export_dynamic_symbol>;
|
||||
|
|
|
@ -518,18 +518,18 @@ SymbolBody *SymbolTable<ELFT>::findInCurrentDSO(StringRef Name) {
|
|||
}
|
||||
|
||||
template <class ELFT>
|
||||
void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
|
||||
const object::Archive::Symbol Sym) {
|
||||
Symbol *SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
|
||||
const object::Archive::Symbol Sym) {
|
||||
Symbol *S;
|
||||
bool WasInserted;
|
||||
StringRef Name = Sym.getName();
|
||||
std::tie(S, WasInserted) = insert(Name);
|
||||
if (WasInserted) {
|
||||
replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType);
|
||||
return;
|
||||
return S;
|
||||
}
|
||||
if (!S->body()->isUndefined())
|
||||
return;
|
||||
return S;
|
||||
|
||||
// Weak undefined symbols should not fetch members from archives. If we were
|
||||
// to keep old symbol we would not know that an archive member was available
|
||||
|
@ -540,11 +540,12 @@ void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
|
|||
// to preserve its type. FIXME: Move the Type field to Symbol.
|
||||
if (S->isWeak()) {
|
||||
replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type);
|
||||
return;
|
||||
return S;
|
||||
}
|
||||
std::pair<MemoryBufferRef, uint64_t> MBInfo = F->getMember(&Sym);
|
||||
if (!MBInfo.first.getBuffer().empty())
|
||||
addFile(createObjectFile(MBInfo.first, F->getName(), MBInfo.second));
|
||||
return S;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
|
||||
const typename ELFT::Verdef *Verdef);
|
||||
|
||||
void addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S);
|
||||
Symbol *addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S);
|
||||
void addLazyObject(StringRef Name, LazyObjectFile &Obj);
|
||||
Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther,
|
||||
uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *File);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.globl fn
|
||||
fn:
|
||||
nop
|
|
@ -0,0 +1,30 @@
|
|||
// 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/exclude-libs.s -o %t2.o
|
||||
// RUN: mkdir -p %t.dir
|
||||
// RUN: rm -f %t.dir/exc.a
|
||||
// RUN: llvm-ar rcs %t.dir/exc.a %t2.o
|
||||
|
||||
// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe
|
||||
// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=DEFAULT %s
|
||||
|
||||
// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=foo,bar
|
||||
// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=DEFAULT %s
|
||||
|
||||
// RUN: ld.lld -shared %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 %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 %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
|
||||
|
||||
.globl fn
|
||||
foo:
|
||||
call fn@PLT
|
Loading…
Reference in New Issue