aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2007-10-15 00:34:48 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2007-10-15 00:34:48 +0000
commita56cc074cf692280c8cac7b170fe0013cd476591 (patch)
treedbab8bde557395fe31a50bd02a4a2a658eca5606
parentf7cc99de8df62d6459c03a46e268251b00dd8fa3 (diff)
downloadpaludis-a56cc074cf692280c8cac7b170fe0013cd476591.tar.gz
paludis-a56cc074cf692280c8cac7b170fe0013cd476591.tar.xz
Always recognise libraries in directories listed in ld.so.conf, even
if we're not actually checking them for brokenness.
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/broken_linkage_finder.cc23
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/configuration.cc27
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/configuration.hh2
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/configuration_TEST.cc2
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc129
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.hh3
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc5
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.hh1
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/linkage_checker.hh1
9 files changed, 168 insertions, 25 deletions
diff --git a/src/clients/reconcilio/broken_linkage_finder/broken_linkage_finder.cc b/src/clients/reconcilio/broken_linkage_finder/broken_linkage_finder.cc
index 81191af..c77495b 100644
--- a/src/clients/reconcilio/broken_linkage_finder/broken_linkage_finder.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/broken_linkage_finder.cc
@@ -67,6 +67,7 @@ namespace paludis
std::string library;
std::vector<tr1::shared_ptr<LinkageChecker> > checkers;
+ std::set<FSEntry> extra_lib_dirs;
Mutex mutex;
@@ -124,7 +125,7 @@ BrokenLinkageFinder::BrokenLinkageFinder(const Environment * env, const std::str
Context ctx("When checking for broken linkage in '" + stringify(env->root()) + "':");
- _imp->checkers.push_back(tr1::shared_ptr<LinkageChecker>(new ElfLinkageChecker(library)));
+ _imp->checkers.push_back(tr1::shared_ptr<LinkageChecker>(new ElfLinkageChecker(env->root(), library)));
if (library.empty())
_imp->checkers.push_back(tr1::shared_ptr<LinkageChecker>(new LibtoolLinkageChecker(env->root())));
@@ -144,9 +145,21 @@ BrokenLinkageFinder::BrokenLinkageFinder(const Environment * env, const std::str
ll_debug, lc_context, "After resolving symlinks and pruning subdirectories, SEARCH_DIRS=\"" +
join(search_dirs_pruned.begin(), search_dirs_pruned.end(), " ") + "\"");
+ std::transform(_imp->config.begin_ld_so_conf(), _imp->config.end_ld_so_conf(),
+ std::inserter(_imp->extra_lib_dirs, _imp->extra_lib_dirs.begin()),
+ tr1::bind(realpath_with_current_and_root, _1, FSEntry("/"), env->root()));
+
parallel_for_each(search_dirs_pruned.begin(), search_dirs_pruned.end(),
tr1::bind(&Implementation<BrokenLinkageFinder>::search_directory, _imp.get(), _1));
+ for (Configuration::DirsIterator it(_imp->extra_lib_dirs.begin()),
+ it_end(_imp->extra_lib_dirs.end()); it_end != it; ++it)
+ {
+ Log::get_instance()->message(ll_debug, lc_context, "Need to check for extra libraries in '" + stringify(env->root() / *it) + "'");
+ std::for_each(_imp->checkers.begin(), _imp->checkers.end(),
+ tr1::bind(&LinkageChecker::add_extra_lib_dir, _1, env->root() / *it));
+ }
+
tr1::function<void (const FSEntry &, const std::string &)> callback(
tr1::bind(&Implementation<BrokenLinkageFinder>::add_breakage, _imp.get(), _1, _2));
std::for_each(_imp->checkers.begin(), _imp->checkers.end(),
@@ -186,13 +199,19 @@ Implementation<BrokenLinkageFinder>::walk_directory(const FSEntry & directory)
{
using namespace tr1::placeholders;
- if (config.dir_is_masked(directory.strip_leading(env->root())))
+ FSEntry without_root(directory.strip_leading(env->root()));
+ if (config.dir_is_masked(without_root))
{
Log::get_instance()->message(ll_debug, lc_context, "'" + stringify(directory) + "' is search-masked");
return;
}
Log::get_instance()->message(ll_debug, lc_context, "Entering directory '" + stringify(directory) + "'");
+ {
+ Lock l(mutex);
+ extra_lib_dirs.erase(without_root);
+ }
+
try
{
parallel_for_each(DirIterator(directory, false), DirIterator(),
diff --git a/src/clients/reconcilio/broken_linkage_finder/configuration.cc b/src/clients/reconcilio/broken_linkage_finder/configuration.cc
index aa4485c..011fa48 100644
--- a/src/clients/reconcilio/broken_linkage_finder/configuration.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/configuration.cc
@@ -51,6 +51,7 @@ namespace paludis
std::vector<std::string> ld_library_mask;
std::vector<FSEntry> search_dirs;
std::vector<FSEntry> search_dirs_mask;
+ std::vector<FSEntry> ld_so_conf;
void load_from_environment();
void load_from_etc_revdep_rebuild(const FSEntry &);
@@ -142,6 +143,14 @@ Configuration::Configuration(const FSEntry & root) :
cleanup("LD_LIBRARY_MASK", _imp->ld_library_mask, root);
cleanup("SEARCH_DIRS", _imp->search_dirs, root);
cleanup("SEARCH_DIRS_MASK", _imp->search_dirs_mask, root);
+
+ // don't need the extra cleanup here
+ std::sort(_imp->ld_so_conf.begin(), _imp->ld_so_conf.end());
+ _imp->ld_so_conf.erase(std::unique(_imp->ld_so_conf.begin(), _imp->ld_so_conf.end()),
+ _imp->ld_so_conf.end());
+ Log::get_instance()->message(
+ ll_debug, lc_context, "Final ld.so.conf contents is \"" +
+ join(_imp->ld_so_conf.begin(), _imp->ld_so_conf.end(), " ") + "\"");
}
Configuration::~Configuration()
@@ -252,6 +261,7 @@ Implementation<Configuration>::load_from_etc_ld_so_conf(const FSEntry & root)
{
Log::get_instance()->message(ll_debug, lc_context, "Got " + join(lines.begin(), lines.end(), " "));
std::copy(lines.begin(), lines.end(), std::back_inserter(search_dirs));
+ std::copy(lines.begin(), lines.end(), std::back_inserter(ld_so_conf));
}
}
else if (etc_ld_so_conf.exists())
@@ -269,6 +279,7 @@ Implementation<Configuration>::add_defaults()
"/bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*");
static const std::string default_search_dirs_mask(
"/opt/OpenOffice /usr/lib*/openoffice /lib*/modules");
+ static const std::string default_ld_so_conf("/lib /usr/lib");
Log::get_instance()->message(ll_debug, lc_context, "Got LD_LIBRARY_MASK=\"" + default_ld_library_mask + "\"");
WhitespaceTokeniser::get_instance()->tokenise(
@@ -281,6 +292,10 @@ Implementation<Configuration>::add_defaults()
Log::get_instance()->message(ll_debug, lc_context, "Got SEARCH_DIRS_MASK=\"" + default_search_dirs_mask + "\"");
WhitespaceTokeniser::get_instance()->tokenise(
default_search_dirs_mask, std::back_inserter(search_dirs_mask));
+
+ Log::get_instance()->message(ll_debug, lc_context, "Default ld.so.conf contents is \"" + default_ld_so_conf + "\"");
+ WhitespaceTokeniser::get_instance()->tokenise(
+ default_ld_so_conf, std::back_inserter(ld_so_conf));
}
Configuration::DirsIterator
@@ -295,6 +310,18 @@ Configuration::end_search_dirs() const
return DirsIterator(_imp->search_dirs.end());
}
+Configuration::DirsIterator
+Configuration::begin_ld_so_conf() const
+{
+ return DirsIterator(_imp->ld_so_conf.begin());
+}
+
+Configuration::DirsIterator
+Configuration::end_ld_so_conf() const
+{
+ return DirsIterator(_imp->ld_so_conf.end());
+}
+
bool
Configuration::dir_is_masked(const FSEntry & dir) const
{
diff --git a/src/clients/reconcilio/broken_linkage_finder/configuration.hh b/src/clients/reconcilio/broken_linkage_finder/configuration.hh
index d876787..445ca29 100644
--- a/src/clients/reconcilio/broken_linkage_finder/configuration.hh
+++ b/src/clients/reconcilio/broken_linkage_finder/configuration.hh
@@ -42,6 +42,8 @@ namespace broken_linkage_finder
typedef libwrapiter::ForwardIterator<Configuration, const paludis::FSEntry> DirsIterator;
DirsIterator begin_search_dirs() const PALUDIS_ATTRIBUTE((warn_unused_result));
DirsIterator end_search_dirs() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ DirsIterator begin_ld_so_conf() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ DirsIterator end_ld_so_conf() const PALUDIS_ATTRIBUTE((warn_unused_result));
bool dir_is_masked(const paludis::FSEntry &) const PALUDIS_ATTRIBUTE((warn_unused_result));
bool lib_is_masked(const std::string &) const PALUDIS_ATTRIBUTE((warn_unused_result));
diff --git a/src/clients/reconcilio/broken_linkage_finder/configuration_TEST.cc b/src/clients/reconcilio/broken_linkage_finder/configuration_TEST.cc
index 7d9e241..0cb6da5 100644
--- a/src/clients/reconcilio/broken_linkage_finder/configuration_TEST.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/configuration_TEST.cc
@@ -50,6 +50,8 @@ namespace test_cases
TEST_CHECK_EQUAL(join(config.begin_search_dirs(), config.end_search_dirs(), " "),
"/alib /barbin /barlib/foo /bazbin /bin /blib /foobin /foolib/bar /lib32 /lib64 /quuxlib /sbin /usr/bin /usr/lib* /usr/sbin");
+ TEST_CHECK_EQUAL(join(config.begin_ld_so_conf(), config.end_ld_so_conf(), " "),
+ "/barlib/foo /foolib/bar /lib /usr/lib");
TEST_CHECK(config.dir_is_masked(FSEntry("/meh")));
TEST_CHECK(config.dir_is_masked(FSEntry("/quuxlib/quux")));
diff --git a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
index 863445c..f13a9f4 100644
--- a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
@@ -20,6 +20,7 @@
#include "elf_linkage_checker.hh"
#include <src/clients/reconcilio/util/iterator.hh>
+#include <src/clients/reconcilio/util/realpath.hh>
#include <src/clients/reconcilio/littlelf/elf.hh>
#include <src/clients/reconcilio/littlelf/elf_dynamic_section.hh>
@@ -56,20 +57,7 @@ namespace
unsigned char _class, _os_abi, _os_abi_version;
bool _bigendian, _mips_n32;
- bool operator< (const ElfArchitecture & other) const
- {
- if (_machine != other._machine)
- return _machine < other._machine;
- if (_class != other._class)
- return _class < other._class;
- if (_os_abi != other._os_abi)
- return _os_abi < other._os_abi;
- if (_os_abi_version != other._os_abi_version)
- return _os_abi_version < other._os_abi_version;
- if (_bigendian != other._bigendian)
- return _bigendian < other._bigendian;
- return _mips_n32 < other._mips_n32;
- }
+ bool operator< (const ElfArchitecture &) const PALUDIS_ATTRIBUTE((warn_unused_result));
static unsigned normalise_arch(unsigned arch)
{
@@ -94,6 +82,22 @@ namespace
{
}
};
+
+ bool
+ ElfArchitecture::operator< (const ElfArchitecture & other) const
+ {
+ if (_machine != other._machine)
+ return _machine < other._machine;
+ if (_class != other._class)
+ return _class < other._class;
+ if (_os_abi != other._os_abi)
+ return _os_abi < other._os_abi;
+ if (_os_abi_version != other._os_abi_version)
+ return _os_abi_version < other._os_abi_version;
+ if (_bigendian != other._bigendian)
+ return _bigendian < other._bigendian;
+ return _mips_n32 < other._mips_n32;
+ }
}
typedef std::multimap<FSEntry, FSEntry> Symlinks;
@@ -104,6 +108,7 @@ namespace paludis
template <>
struct Implementation<ElfLinkageChecker>
{
+ FSEntry root;
std::string library;
Mutex mutex;
@@ -114,18 +119,22 @@ namespace paludis
std::map<ElfArchitecture, std::vector<std::string> > libraries;
Needed needed;
+ std::vector<FSEntry> extra_lib_dirs;
+
template <typename> bool check_elf(const FSEntry &, std::ifstream &);
void handle_library(const FSEntry &, const ElfArchitecture &);
+ template <typename> bool check_extra_elf(const FSEntry &, std::istream &, std::set<ElfArchitecture> &);
- Implementation(const std::string & the_library) :
+ Implementation(const FSEntry & the_root, const std::string & the_library) :
+ root(the_root),
library(the_library)
{
}
};
}
-ElfLinkageChecker::ElfLinkageChecker(const std::string & library) :
- PrivateImplementationPattern<ElfLinkageChecker>(new Implementation<ElfLinkageChecker>(library))
+ElfLinkageChecker::ElfLinkageChecker(const FSEntry & root, const std::string & library) :
+ PrivateImplementationPattern<ElfLinkageChecker>(new Implementation<ElfLinkageChecker>(root, library))
{
}
@@ -242,9 +251,20 @@ ElfLinkageChecker::note_symlink(const FSEntry & link, const FSEntry & target)
}
void
+ElfLinkageChecker::add_extra_lib_dir(const FSEntry & dir)
+{
+ _imp->extra_lib_dirs.push_back(dir);
+}
+
+void
ElfLinkageChecker::need_breakage_added(
const tr1::function<void (const FSEntry &, const std::string &)> & callback)
{
+ using namespace tr1::placeholders;
+
+ typedef std::map<std::string, std::set<ElfArchitecture> > AllMissing;
+ AllMissing all_missing;
+
for (Needed::iterator arch_it(_imp->needed.begin()),
arch_it_end(_imp->needed.end()); arch_it_end != arch_it; ++arch_it)
{
@@ -260,12 +280,77 @@ ElfLinkageChecker::need_breakage_added(
_imp->libraries[arch_it->first].begin(),
_imp->libraries[arch_it->first].end(),
std::back_inserter(missing));
+ for (std::vector<std::string>::const_iterator it(missing.begin()),
+ it_end(missing.end()); it_end != it; ++it)
+ all_missing[*it].insert(arch_it->first);
+ }
+
+ for (std::vector<FSEntry>::const_iterator dir_it(_imp->extra_lib_dirs.begin()),
+ dir_it_end(_imp->extra_lib_dirs.end()); dir_it_end != dir_it; ++dir_it)
+ {
+ Context ctx("When seaching for missing libraries in '" + stringify(*dir_it) + "':");
+
+ for (AllMissing::iterator missing_it(all_missing.begin()),
+ missing_it_end(all_missing.end()); missing_it_end != missing_it; ++missing_it)
+ {
+ if (missing_it->second.empty())
+ continue;
+
+ FSEntry file(dereference_with_root(*dir_it / missing_it->first, _imp->root));
+ if (! file.is_regular_file())
+ {
+ Log::get_instance()->message(ll_debug, lc_context, "'" + stringify(file) + "' is missing or not a regular file");
+ continue;
+ }
+
+ std::ifstream stream(stringify(file).c_str());
+ if (! stream)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Error opening '" + stringify(file) + "': " + strerror(errno));
+ continue;
+ }
+
+ if (! (_imp->check_extra_elf<Elf32Type>(file, stream, missing_it->second) ||
+ _imp->check_extra_elf<Elf64Type>(file, stream, missing_it->second)))
+ Log::get_instance()->message(ll_debug, lc_no_context, "'" + stringify(file) + "' is not an ELF file");
+ }
+ }
+
+ for (AllMissing::const_iterator missing_it(all_missing.begin()),
+ missing_it_end(all_missing.end()); missing_it_end != missing_it; ++missing_it)
+ for (std::set<ElfArchitecture>::const_iterator arch_it(missing_it->second.begin()),
+ arch_it_end(missing_it->second.end()); arch_it_end != arch_it; ++arch_it)
+ std::for_each(_imp->needed[*arch_it][missing_it->first].begin(),
+ _imp->needed[*arch_it][missing_it->first].end(),
+ tr1::bind(callback, _1, missing_it->first));
+
+}
+
+template <typename ElfType_>
+bool
+Implementation<ElfLinkageChecker>::check_extra_elf(const FSEntry & file, std::istream & stream, std::set<ElfArchitecture> & arches)
+{
+ if (! ElfObject<ElfType_>::is_valid_elf(stream))
+ return false;
+
+ Context ctx("When checking '" + stringify(file) + "' as a " + stringify<int>(ElfType_::elf_class * 32) + "-bit ELF file");
- for (std::vector<std::string>::const_iterator req_it(missing.begin()),
- req_it_end(missing.end()); req_it_end != req_it; ++req_it)
- for (std::vector<FSEntry>::const_iterator file_it(arch_it->second[*req_it].begin()),
- file_it_end(arch_it->second[*req_it].end()); file_it_end != file_it; ++file_it)
- callback(*file_it, *req_it);
+ try
+ {
+ ElfObject<ElfType_> elf(stream);
+ if (ET_DYN == elf.get_type())
+ {
+ Log::get_instance()->message(ll_debug, lc_context, "'" + stringify(file) + "' is a library");
+ arches.erase(ElfArchitecture(elf));
+ }
+ else
+ Log::get_instance()->message(ll_debug, lc_context, "'" + stringify(file) + "' is not a library");
}
+ catch (const InvalidElfFileError &)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "'" + stringify(file) + "' appears to be invalid or corrupted");
+ }
+
+ return true;
}
diff --git a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.hh b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.hh
index 22d5a93..ca20d7a 100644
--- a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.hh
+++ b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.hh
@@ -34,12 +34,13 @@ namespace broken_linkage_finder
private paludis::PrivateImplementationPattern<ElfLinkageChecker>
{
public:
- ElfLinkageChecker(const std::string &);
+ ElfLinkageChecker(const paludis::FSEntry &, const std::string &);
virtual ~ElfLinkageChecker();
virtual bool check_file(const paludis::FSEntry &) PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void note_symlink(const paludis::FSEntry &, const paludis::FSEntry &);
+ virtual void add_extra_lib_dir(const paludis::FSEntry &);
virtual void need_breakage_added(
const paludis::tr1::function<void (const paludis::FSEntry &, const std::string &)> &);
};
diff --git a/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc b/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc
index 0d52050..a1a03d0 100644
--- a/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc
@@ -154,6 +154,11 @@ LibtoolLinkageChecker::note_symlink(const FSEntry &, const FSEntry &)
}
void
+LibtoolLinkageChecker::add_extra_lib_dir(const FSEntry &)
+{
+}
+
+void
LibtoolLinkageChecker::need_breakage_added(
const tr1::function<void (const FSEntry &, const std::string &)> & callback)
{
diff --git a/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.hh b/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.hh
index aa370ef..3fcf1b9 100644
--- a/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.hh
+++ b/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.hh
@@ -37,6 +37,7 @@ namespace broken_linkage_finder
virtual bool check_file(const paludis::FSEntry &) PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void note_symlink(const paludis::FSEntry &, const paludis::FSEntry &);
+ virtual void add_extra_lib_dir(const paludis::FSEntry &);
virtual void need_breakage_added(
const paludis::tr1::function<void (const paludis::FSEntry &, const std::string &)> &);
};
diff --git a/src/clients/reconcilio/broken_linkage_finder/linkage_checker.hh b/src/clients/reconcilio/broken_linkage_finder/linkage_checker.hh
index 3e30f6e..70ea20f 100644
--- a/src/clients/reconcilio/broken_linkage_finder/linkage_checker.hh
+++ b/src/clients/reconcilio/broken_linkage_finder/linkage_checker.hh
@@ -44,6 +44,7 @@ namespace broken_linkage_finder
virtual bool check_file(const paludis::FSEntry &) PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
virtual void note_symlink(const paludis::FSEntry &, const paludis::FSEntry &) = 0;
+ virtual void add_extra_lib_dir(const paludis::FSEntry &) = 0;
virtual void need_breakage_added(
const paludis::tr1::function<void (const paludis::FSEntry &, const std::string &)> &) = 0;