def Libraries(pkg_data, error_mgr, logger, messenger, path_and_pkg_by_basename, pkg_by_path): """Checks shared libraries. Returns: [ (u"CSWfoo", "why is this needed"), ] New idea, a list of reasons: [ [(u"CSWfoo", "why is it needed"), (u"CSWfooalt", "there must be a reason"), (u"CSWfooyetanother", "here's another one")], [(u"CSWbar", "this serves another purpose")], ] """ pkgname = pkg_data["basic_stats"]["pkgname"] logger.debug("Libraries(): pkgname = %s", repr(pkgname)) isalist = pkg_data["isalist"] ldd_emulator = ldd_emul.LddEmulator() orphan_sonames = [] for binary_info in pkg_data["binaries_dump_info"]: binary_path, binary_basename = os.path.split(binary_info["path"]) for soname in binary_info["needed sonames"]: orphan_sonames_tmp = ProcessSoname(ldd_emulator, soname, path_and_pkg_by_basename, binary_info, isalist, binary_path, logger, error_mgr, pkgname, messenger) orphan_sonames.extend(orphan_sonames_tmp) orphan_sonames = set(orphan_sonames) for soname, binary_path in orphan_sonames: if soname not in ALLOWED_ORPHAN_SONAMES: error_mgr.ReportError(pkgname, "soname-not-found", "%s is needed by %s" % (soname, binary_path))
def setUp(self): self.pkgmap_mocker = mox.Mox() self.e = ldd_emul.LddEmulator()
def Libraries(pkg_data, error_mgr, logger, messenger, path_and_pkg_by_basename, pkg_by_path): """Checks shared libraries. Returns: [ (u"CSWfoo", "why is this needed"), ] New idea, a list of reasons: [ [(u"CSWfoo", "why is it needed"), (u"CSWfooalt", "there must be a reason"), (u"CSWfooyetanother", "here's another one")], [(u"CSWbar", "this serves another purpose")], ] """ pkgname = pkg_data["basic_stats"]["pkgname"] logger.debug("Libraries(): pkgname = %s", repr(pkgname)) isalist = pkg_data["isalist"] ldd_emulator = ldd_emul.LddEmulator() orphan_sonames = [] for binary_info in pkg_data["binaries_dump_info"]: binary_path, binary_basename = os.path.split(binary_info["path"]) for soname in binary_info["needed sonames"]: orphan_sonames_tmp = ProcessSoname(ldd_emulator, soname, path_and_pkg_by_basename, binary_info, isalist, binary_path, logger, error_mgr, pkgname, messenger) orphan_sonames.extend(orphan_sonames_tmp) sonames_unused = set() ldd_info = pkg_data['ldd_info'][binary_info["path"]] for ldd_response in ldd_info: if (ldd_response['state'] == 'soname-unused' and ldd_response['soname'] not in BASE_SOLARIS_LIBRARIES): sonames_unused.add(ldd_response['soname']) messenger.Message( "Binary %s links to library %s but doesn't seem to use any" " of its symbols. It usually happens because superfluous" " libraries were added to the linker options, either because" " of the configure script itself or because of the" " \"pkg-config --libs\" output of one the dependency." % ("/" + binary_info["path"], ldd_response['soname'])) error_mgr.ReportError( pkgname, "soname-unused", "%s is needed by %s but never used" % (ldd_response['soname'], "/" + binary_info["path"])) # Even when direct binding is enabled, some symbols might not be # directly bound because the library explicitely requested the symbol # not to be drectly bound to. # For example, libc.so.1 does it for symbol sigaction, free, malloc... # So we consider that direct binding is enabled if at least one # symbol is directly bound to because that definitely means that # -B direct or -z direct was used. binary_elf_info = pkg_data["binaries_elf_info"][binary_info["path"]] libs = set(binary_info["needed sonames"]) # we skip the standard Solaris libraries: a lot of plugins only # link to non directly bindable symbols of libc.so.1, librt.so.1 # which trigger false positives. # Direct binding really matters for opencsw libraries so it's # easier and riskless to just skip theses libraries libs.difference_update(BASE_SOLARIS_LIBRARIES) db_libs = set() for syminfo in binary_elf_info['symbol table']: if (syminfo['shndx'] == 'UNDEF' and syminfo['flags'] and 'D' in syminfo['flags'] and 'B' in syminfo['flags']): db_libs.add(syminfo['soname']) no_db_libs = libs.difference(db_libs) # no symbol used means no way to detect if direct binding was # enabled so we must ignore the libraries which were linked # without being used no_db_libs.difference_update(sonames_unused) if no_db_libs: messenger.Message( "No symbol of binary %s is directly bound against the following" " libraries: %s. Please make sure the binaries are compiled using" " the \"-Bdirect\" linker option." % ("/" + binary_info["path"], ", ".join(no_db_libs))) for soname in no_db_libs: error_mgr.ReportError( pkgname, "no-direct-binding", "%s is not directly bound to soname %s" % ("/" + binary_info["path"], soname)) for version_dep in binary_elf_info['version needed']: if (version_dep['soname'] in ALLOWED_VERSION_DEPENDENCIES and not version_dep['version'] in ALLOWED_VERSION_DEPENDENCIES[version_dep['soname']]): messenger.Message( "Binary %s requires interface version %s in library %s which is" " only available in recent Solaris releases." % ("/" + binary_info["path"], version_dep['version'], version_dep['soname'])) error_mgr.ReportError( pkgname, "forbidden-version-interface-dependencies", "%s requires forbidden interface version %s in library %s" % ("/" + binary_info["path"], version_dep['version'], version_dep['soname'])) orphan_sonames = set(orphan_sonames) for soname, binary_path in orphan_sonames: if soname not in ALLOWED_ORPHAN_SONAMES: error_mgr.ReportError(pkgname, "soname-not-found", "%s is needed by %s" % (soname, binary_path))