[ELF] Add --as-needed.
The previous default behavior of LLD is --as-needed. LLD linked against a DSO only if the DSO file was actually used to link an executable (i.e. at least one symbol was resolved using the shared library file.) In this patch I added a boolean flag to FileNode for --as-needed. I also added an accessor to DSO name to shared library file class. llvm-svn: 226274
This commit is contained in:
parent
4286a9bd5a
commit
fa7e8a663f
|
@ -57,9 +57,7 @@ private:
|
|||
class FileNode : public Node {
|
||||
public:
|
||||
explicit FileNode(std::unique_ptr<File> f)
|
||||
: Node(Node::Kind::File), _file(std::move(f)) {}
|
||||
|
||||
virtual ~FileNode() {}
|
||||
: Node(Node::Kind::File), _file(std::move(f)), _asNeeded(false) {}
|
||||
|
||||
static inline bool classof(const Node *a) {
|
||||
return a->kind() == Node::Kind::File;
|
||||
|
@ -67,8 +65,12 @@ public:
|
|||
|
||||
File *getFile() { return _file.get(); }
|
||||
|
||||
void setAsNeeded(bool val) { _asNeeded = val; }
|
||||
bool asNeeded() const { return _asNeeded; }
|
||||
|
||||
protected:
|
||||
std::unique_ptr<File> _file;
|
||||
bool _asNeeded;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
|
|
@ -31,6 +31,11 @@ public:
|
|||
/// symbol. Otherwise return nullptr.
|
||||
virtual const SharedLibraryAtom *exports(StringRef name,
|
||||
bool dataSymbolOnly) const = 0;
|
||||
|
||||
// Returns DSO name. It's the soname (ELF), the install name (MachO) or
|
||||
// the import name (Windows).
|
||||
virtual StringRef getDSOName() const = 0;
|
||||
|
||||
protected:
|
||||
/// only subclasses of SharedLibraryFile can be instantiated
|
||||
explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
|
||||
|
|
|
@ -297,17 +297,14 @@ public:
|
|||
class Attributes {
|
||||
public:
|
||||
Attributes()
|
||||
: _isWholeArchive(false), _asNeeded(false), _isDashlPrefix(false),
|
||||
_isSysRooted(false) {}
|
||||
: _isWholeArchive(false), _isDashlPrefix(false), _isSysRooted(false) {}
|
||||
void setWholeArchive(bool isWholeArchive) {
|
||||
_isWholeArchive = isWholeArchive;
|
||||
}
|
||||
void setAsNeeded(bool asNeeded) { _asNeeded = asNeeded; }
|
||||
void setDashlPrefix(bool isDashlPrefix) { _isDashlPrefix = isDashlPrefix; }
|
||||
void setSysRooted(bool isSysRooted) { _isSysRooted = isSysRooted; }
|
||||
|
||||
bool _isWholeArchive;
|
||||
bool _asNeeded;
|
||||
bool _isDashlPrefix;
|
||||
bool _isSysRooted;
|
||||
};
|
||||
|
|
|
@ -259,7 +259,6 @@ evaluateLinkerScript(ELFLinkingContext &ctx, StringRef path,
|
|||
// TODO : Propagate Set WholeArchive/dashlPrefix
|
||||
ELFLinkingContext::Attributes attr;
|
||||
attr.setSysRooted(sysroot);
|
||||
attr.setAsNeeded(path._asNeeded);
|
||||
attr.setDashlPrefix(path._isDashlPrefix);
|
||||
|
||||
ErrorOr<StringRef> pathOrErr = path._isDashlPrefix
|
||||
|
@ -357,6 +356,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
int numfiles = 0;
|
||||
|
||||
ELFLinkingContext::Attributes attributes;
|
||||
bool asNeeded = false;
|
||||
|
||||
bool _outputOptionSet = false;
|
||||
|
||||
|
@ -516,11 +516,11 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
break;
|
||||
|
||||
case OPT_as_needed:
|
||||
attributes.setAsNeeded(true);
|
||||
asNeeded = true;
|
||||
break;
|
||||
|
||||
case OPT_no_as_needed:
|
||||
attributes.setAsNeeded(false);
|
||||
asNeeded = false;
|
||||
break;
|
||||
|
||||
case OPT_defsym: {
|
||||
|
@ -612,7 +612,9 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
|||
for (std::unique_ptr<File> &file : files) {
|
||||
if (ctx->logInputFiles())
|
||||
diagnostics << file->path() << "\n";
|
||||
ctx->getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
|
||||
auto node = llvm::make_unique<FileNode>(std::move(file));
|
||||
node->setAsNeeded(asNeeded);
|
||||
ctx->getNodes().push_back(std::move(node));
|
||||
}
|
||||
numfiles += files.size();
|
||||
break;
|
||||
|
|
|
@ -41,7 +41,6 @@ Missing Options
|
|||
* -y,--trace-symbol
|
||||
* -z (keywords need to be implemented)
|
||||
* --accept-unknown-input-arch,--no-accept-unknown-input-arch
|
||||
* --as-needed,--no-as-needed
|
||||
* -Bdynamic,-dy,-call_shared
|
||||
* -Bgroup
|
||||
* -dn,-non_shared
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
*this, name, _soname, sym->second._symbol);
|
||||
}
|
||||
|
||||
StringRef getDSOName() const override { return _soname; }
|
||||
|
||||
protected:
|
||||
std::error_code doParse() override {
|
||||
std::error_code ec;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "TargetLayout.h"
|
||||
#include "lld/Core/Instrumentation.h"
|
||||
#include "lld/Core/Parallel.h"
|
||||
#include "lld/Core/SharedLibraryFile.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
|
@ -143,6 +144,9 @@ protected:
|
|||
LLD_UNIQUE_BUMP_PTR(HashSection<ELFT>) _hashTable;
|
||||
llvm::StringSet<> _soNeeded;
|
||||
/// @}
|
||||
|
||||
private:
|
||||
static StringRef maybeGetSOName(Node *node);
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -177,6 +181,17 @@ void OutputELFWriter<ELFT>::buildStaticSymbolTable(const File &file) {
|
|||
_symtab->addSymbol(a, ELF::SHN_UNDEF);
|
||||
}
|
||||
|
||||
// Returns the DSO name for a given input file if it's a shared library
|
||||
// file and not marked as --as-needed.
|
||||
template <class ELFT>
|
||||
StringRef OutputELFWriter<ELFT>::maybeGetSOName(Node *node) {
|
||||
if (auto *fnode = dyn_cast<FileNode>(node))
|
||||
if (!fnode->asNeeded())
|
||||
if (auto *file = dyn_cast<SharedLibraryFile>(fnode->getFile()))
|
||||
return file->getDSOName();
|
||||
return "";
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
|
||||
ScopedTask task(getDefaultDomain(), "buildDynamicSymbolTable");
|
||||
|
@ -189,6 +204,11 @@ void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
|
|||
if (isNeededTagRequired(sla))
|
||||
_soNeeded.insert(sla->loadName());
|
||||
}
|
||||
for (const std::unique_ptr<Node> &node : _context.getNodes()) {
|
||||
StringRef soname = maybeGetSOName(node.get());
|
||||
if (!soname.empty())
|
||||
_soNeeded.insert(soname);
|
||||
}
|
||||
// Never mark the dynamic linker as DT_NEEDED
|
||||
_soNeeded.erase(sys::path::filename(_context.getInterpreter()));
|
||||
for (const auto &loadName : _soNeeded) {
|
||||
|
|
|
@ -273,6 +273,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
StringRef getDSOName() const override { return _installName; }
|
||||
|
||||
std::error_code doParse() override {
|
||||
// Convert binary file to normalized mach-o.
|
||||
auto normFile = normalized::readBinary(_mb, _ctx->arch());
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# RUN: yaml2obj -format=elf -docnum 3 %s > %t-main.o
|
||||
# RUN: lld -flavor gnu -target mipsel -shared -o %t-bar.so %t-bar.o
|
||||
# RUN: lld -flavor gnu -target mipsel -shared -o %t-foo.so %t-foo.o %t-bar.so
|
||||
# RUN: lld -flavor gnu -target mipsel -e T0 -o %t.exe \
|
||||
# RUN: lld -flavor gnu -target mipsel -e T0 -o %t.exe --as-needed \
|
||||
# RUN: %t-main.o %t-foo.so %t-bar.so
|
||||
# RUN: llvm-readobj -dt -dynamic-table %t.exe | FileCheck %s
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: --as-needed %p/Inputs/shared.so-x86-64 %p/Inputs/libifunc.x86-64.so \
|
||||
RUN: -o %t1 -e main --allow-shlib-undefined
|
||||
RUN: llvm-readobj -dynamic-table %t1 | FileCheck %s -check-prefix AS_NEEDED
|
||||
|
||||
AS_NEEDED: NEEDED SharedLibrary (shared.so-x86-64)
|
||||
AS_NEEDED-NOT: NEEDED SharedLibrary (libifunc.x86-64.so)
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 %p/Inputs/libifunc.x86-64.so \
|
||||
RUN: -o %t2 -e main --allow-shlib-undefined
|
||||
RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s -check-prefix NO_AS_NEEDED
|
||||
|
||||
NO_AS_NEEDED: NEEDED SharedLibrary (shared.so-x86-64)
|
||||
NO_AS_NEEDED: NEEDED SharedLibrary (libifunc.x86-64.so)
|
Loading…
Reference in New Issue