[lld] r305920 - Implement the --exclude-libs option.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 21 08:36:25 PDT 2017
Author: ruiu
Date: Wed Jun 21 10:36:24 2017
New Revision: 305920
URL: http://llvm.org/viewvc/llvm-project?rev=305920&view=rev
Log:
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
Added:
lld/trunk/test/ELF/Inputs/exclude-libs.s
lld/trunk/test/ELF/exclude-libs.s
Modified:
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputFiles.h
lld/trunk/ELF/Options.td
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=305920&r1=305919&r2=305920&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Jun 21 10:36:24 2017
@@ -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:
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.
Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=305920&r1=305919&r2=305920&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Wed Jun 21 10:36:24 2017
@@ -632,8 +632,9 @@ ArchiveFile::ArchiveFile(std::unique_ptr
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.
Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=305920&r1=305919&r2=305920&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Wed Jun 21 10:36:24 2017
@@ -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 {
Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=305920&r1=305919&r2=305920&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Wed Jun 21 10:36:24 2017
@@ -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">,
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>;
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=305920&r1=305919&r2=305920&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Jun 21 10:36:24 2017
@@ -518,18 +518,18 @@ SymbolBody *SymbolTable<ELFT>::findInCur
}
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(A
// 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>
Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=305920&r1=305919&r2=305920&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Wed Jun 21 10:36:24 2017
@@ -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);
Added: lld/trunk/test/ELF/Inputs/exclude-libs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/exclude-libs.s?rev=305920&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/exclude-libs.s (added)
+++ lld/trunk/test/ELF/Inputs/exclude-libs.s Wed Jun 21 10:36:24 2017
@@ -0,0 +1,3 @@
+.globl fn
+fn:
+ nop
Added: lld/trunk/test/ELF/exclude-libs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/exclude-libs.s?rev=305920&view=auto
==============================================================================
--- lld/trunk/test/ELF/exclude-libs.s (added)
+++ lld/trunk/test/ELF/exclude-libs.s Wed Jun 21 10:36:24 2017
@@ -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 at PLT
More information about the llvm-commits
mailing list