[csw-maintainers] Checkpkg test for direct binding
Maciej (Matchek) Bliziński
maciej at opencsw.org
Sat Aug 25 18:24:55 CEST 2012
2012/8/25 Yann Rouillard <yann at pleiades.fr.eu.org>
> Hi everybody,
>
> As discussed previously in the direct binding discussion, here is the new
> checkpkg test I am proposing to add to ensure direct binding is enabled in
> packages.
> Of course the idea is to enable this check when we agree on enabling
> direct binding and after having tested it on a first set of package.
>
> The full patch is attached, and I put an inline version without the unit
> test part for easy commenting.
>
> Feedbacks are welcome.
>
> Yann
>
> diff -ur v2.orig//lib/python/dependency_checks.py
> v2/lib/python/dependency_checks.py
> --- v2.orig//lib/python/dependency_checks.py Thu Aug 16 12:05:42 2012
> +++ v2/lib/python/dependency_checks.py Sat Aug 25 16:14:45 2012
> @@ -47,8 +47,8 @@
>
> def ProcessSoname(
> ldd_emulator,
> - soname, path_and_pkg_by_basename, binary_info, isalist, binary_path,
> logger,
> - error_mgr,
> + soname, path_and_pkg_by_basename, binary_info, isalist, binary_path,
> needed_symbols,
> + logger, error_mgr,
> pkgname, messenger):
> """This is not an ideal name for this function.
>
> @@ -57,6 +57,28 @@
> """
> logging.debug("ProcessSoname(), %s %s"
> % (binary_info["path"], soname))
> +
> + # 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 and
> realloc
> + # 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.
> + direct_bind = False
> + for syminfo in needed_symbols:
> + if ('D' in syminfo['flags'] and 'B' in syminfo['flags']):
>
The parentheses are not necessary.
> + direct_bind = True
> + break
> +
> + if not direct_bind:
> + messenger.Message(
> + "No symbol of binary %s is directly binded against library %s. "
> + "Please make sure the binaries are compiled using the \"-Bdirect\"
> linker option."
> + % ("/" + binary_info["path"], soname))
> + error_mgr.ReportError(
> + pkgname, "no-direct-binding",
> + "%s is not directly binded to soname %s" % ("/" +
> binary_info["path"], soname))
> +
> orphan_sonames = []
> resolved = False
> path_list = path_and_pkg_by_basename[soname].keys()
> @@ -146,11 +168,22 @@
> orphan_sonames = []
> for binary_info in pkg_data["binaries_dump_info"]:
> binary_path, binary_basename = os.path.split(binary_info["path"])
> +
> + binary_needed_symbols =
> pkg_data["needed_symbols"][binary_info["path"]]
>
We need to think whether we will reindex all packages, or we'll accept
older data structures without throwing IndexError in the line above.
> for soname in binary_info["needed sonames"]:
> + if soname in binary_needed_symbols:
> + needed_symbols = binary_needed_symbols[soname]
> + else:
> + # If we are here, that means we got no information on symbols.
> + # No syminfo section was present in the elf file, that definitely
> + # imply that -Bdirect or -z direct was not used and the subsequent
> + # check on direct binding will catch it because it will find not symbols
> + needed_symbols = []
> +
> orphan_sonames_tmp = ProcessSoname(
> ldd_emulator,
> - soname, path_and_pkg_by_basename, binary_info, isalist,
> binary_path, logger,
> - error_mgr,
> + soname, path_and_pkg_by_basename, binary_info, isalist,
> binary_path, needed_symbols,
> + logger, error_mgr,
> pkgname, messenger)
> orphan_sonames.extend(orphan_sonames_tmp)
>
> diff -ur v2.orig//lib/python/dependency_checks_test.py
> v2/lib/python/dependency_checks_test.py
> --- v2.orig//lib/python/dependency_checks_test.py Tue Jun 5 23:52:51 2012
> +++ v2/lib/python/dependency_checks_test.py Sat Aug 25 13:37:57 2012
> @@ -258,6 +258,8 @@
> '/opt/csw/share/man': [u'CSWcommon', u'CSWgnuplot'],
> '/opt/csw/share/man/man1': ['CSWtree'],
> '/opt/csw/share/man/man1/tree.1': ['CSWtree']}
> + self.error_mgr_mock.ReportError('CSWtree', 'no-direct-binding',
> + '/opt/csw/bin/tree is not directly binded to soname libc.so.1')
> self.error_mgr_mock.NeedFile('CSWtree', u'/usr/lib/libc.so.1',
> 'opt/csw/bin/tree needs the libc.so.1 soname')
> self.mox.ReplayAll()
> diff -ur v2.orig//lib/python/inspective_package.py
> v2/lib/python/inspective_package.py
> --- v2.orig//lib/python/inspective_package.py Thu Aug 23 23:56:57 2012
> +++ v2/lib/python/inspective_package.py Sat Aug 25 16:17:17 2012
> @@ -229,6 +229,45 @@
>
> return defined_symbols
>
> +
> + def GetNeededSymbols(self):
> + """Returns symbols needed for packaged ELF objects to work
> +
> + To do this we parse output lines from elfdump -y, that command
> + will give us the content of the .SUNW_syminfo section which
> + contains additionnal informations on symbols linking.
> + """
> + binaries = self.ListBinaries()
> + needed_symbols = {}
> +
> + for binary in binaries:
> + binary_abspath = os.path.join(self.directory, "root", binary)
> + # elfdump is the only tool that give us the syminfo flags
> + args = ["/usr/ccs/bin/elfdump", "-y", binary_abspath]
> + elfdump_proc = subprocess.Popen(
> + args,
> + stdout=subprocess.PIPE,
> + stderr=subprocess.PIPE)
> + stdout, stderr = elfdump_proc.communicate()
> + retcode = elfdump_proc.wait()
> + if retcode:
> + logging.error("%s returned an error: %s", args, stderr)
> + continue
> + elfdump_out = stdout.splitlines()
> +
> + needed_symbols[binary] = {}
> + for line in elfdump_out:
> + syminfo = self._ParseElfdumpSyminfoLine(line)
> + if not syminfo:
> + continue
>
In what circumstances does syminfo come back empty? Is it when we can't
parse the text output?
> + if syminfo['library']:
> + library = syminfo['library']
> + del syminfo['library']
>
Will the del above actually free anything? If the whole syminfo stays
around, all its elements will too.
> + symbols = needed_symbols[binary].setdefault(library, [])
> + symbols.append(syminfo)
> +
> + return needed_symbols
> +
> def GetLddMinusRlines(self):
> """Returns ldd -r output."""
> binaries = self.ListBinaries()
> @@ -274,6 +313,22 @@
> sym = { 'address': fields[0], 'type': fields[1], 'name': fields[2] }
> return sym
>
> + def _ParseElfdumpSyminfoLine(self, line):
> + blank_line = (r'^\s*$')
> + header_line = (r'^(?:Syminfo
> Section:\s+.SUNW_syminfo|\s*index\s+flags\s+bound\s+to\s+symbol)\s*$')
> + needed_symbol =
> (r'\s*\[\d+\]\s+(?P<flags>[ABCDFILNPS]+)\s*(\[\d+\]\s+(?P<library>.*\S)|<self>)?\s+(?P<symbol>.*\S)\s*')
> + common_re = (r"(?:%s|%s|%s)" % (blank_line, header_line,
> needed_symbol))
> +
> + m = re.match(common_re, line)
> + if not m:
> + raise package.StdoutSyntaxError("Could not parse %s with %s"
> + % (repr(line), common_re))
> + syminfo = m.groupdict()
> + if 'library' in syminfo and syminfo['library']:
> + return syminfo
> + else:
> + return None
> +
> def _ParseLddDashRline(self, line, binary=None):
> found_re = r"^\t(?P<soname>\S+)\s+=>\s+(?P<path_found>\S+)"
> symbol_not_found_re = (r"^\tsymbol not found:\s(?P<symbol>\S+)\s+"
> diff -ur v2.orig//lib/python/package_stats.py
> v2/lib/python/package_stats.py
> --- v2.orig//lib/python/package_stats.py Fri Aug 10 02:12:10 2012
> +++ v2/lib/python/package_stats.py Sat Aug 25 15:58:49 2012
> @@ -209,6 +209,7 @@
> "files_metadata": dir_pkg.GetFilesMetadata(),
> "mtime": self.GetMtime(),
> "ldd_info": dir_pkg.GetLddMinusRlines(),
> + "needed_symbols": dir_pkg.GetNeededSymbols(),
> }
> self.SaveStats(pkg_stats)
> logging.debug("Statistics of %s have been collected.",
> repr(dir_pkg.pkgname))
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.opencsw.org/pipermail/maintainers/attachments/20120825/d3215845/attachment-0001.html>
More information about the maintainers
mailing list