Control: tag -1 + patch Control: severity -1 serious Hi Guillem,
On Sun, 13 Nov 2016, Guillem Jover wrote: > > The /usr merge violates core assumptions in dpkg-shlibdeps. The reason > > that amd64 isn't broken is sheer luck. > > /etc/ld.so.conf.d/x86_64-linux-gnu.conf lists /lib before /usr/lib, so > > dpkg-shlibdeps considers that first. Swapping them or simply removing > > /lib (as seems reasonable on a merged /usr), breaks almost any build on > > amd64 (e.g. dash). The breakage on amd64 is simply hidden. > > Right. I'm happy to assist people who want to fix this to try to find > a proper solution in dpkg-dev, but I'm not planning on spending time > on this on my own. Please find two patches attached. I checked that the command below was failing with the current dpkg-dev and it did no longer fail with the updated one. $ sbuild -d sid --add-depends=usrmerge --chroot-setup-commands="sed -i 's#^/usr##;t;s#^/lib#/usr&#' /etc/ld.so.conf.d/x86_64-linux-gnu.conf" dash I believe my patch to be correct and clean. > Err, well exactly because usemerge is a major hack, and I'm actually > surprised we are deploying systems by default with that. As an It's easier to push work upon others... to be honest the code (that I wrote) in dpkg-dev that tries to identifiy the canonical version of the library is also somewhat hackish. I think the updated code that I submitted works better in all weird corner cases that we could think of. I'm happy to assist you shall any regression be found. Cheers, -- Raphaël Hertzog ◈ Debian Developer Support Debian LTS: http://www.freexian.com/services/debian-lts.html Learn to master Debian: http://debian-handbook.info/get/
>From d2e19afa0f80a955b66ad133c4ebd5b1458bd8ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hert...@debian.org> Date: Mon, 14 Nov 2016 11:46:09 +0100 Subject: [PATCH 1/2] Dpkg::Shlibs: add find_library_locations() This new functions returns all paths/locations where the library has been found. Where find_library() has some tricks to try to identify the canonical version of the library, this one is much simpler: it scans all directories from the library path and returns every place where it has been found. --- scripts/Dpkg/Shlibs.pm | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/scripts/Dpkg/Shlibs.pm b/scripts/Dpkg/Shlibs.pm index c6221c4..dc0276a 100644 --- a/scripts/Dpkg/Shlibs.pm +++ b/scripts/Dpkg/Shlibs.pm @@ -1,4 +1,4 @@ -# Copyright © 2007 Raphaël Hertzog <hert...@debian.org> +# Copyright © 2007,2016 Raphaël Hertzog <hert...@debian.org> # Copyright © 2007-2008, 2012-2015 Guillem Jover <guil...@debian.org> # # This program is free software; you can redistribute it and/or modify @@ -20,13 +20,14 @@ use strict; use warnings; use feature qw(state); -our $VERSION = '0.02'; +our $VERSION = '0.03'; our @EXPORT_OK = qw( blank_library_paths setup_library_paths get_library_paths add_library_dir find_library + find_library_locations ); use Exporter qw(import); @@ -174,4 +175,26 @@ sub find_library { return; } +sub find_library_locations { + my ($lib, $rpath, $format, $root) = @_; + + setup_library_paths() if not $librarypaths_init; + + my @librarypaths = (@{$rpath}, @custom_librarypaths, @system_librarypaths); + my @locations; + + $root //= ''; + $root =~ s{/+$}{}; + foreach my $dir (@librarypaths) { + my $checkdir = "$root$dir"; + if (-e "$checkdir/$lib") { + my $libformat = Dpkg::Shlibs::Objdump::get_format("$checkdir/$lib"); + if ($format eq $libformat) { + push @locations, canonpath("$checkdir/$lib"); + } + } + } + return @locations; +} + 1; -- 2.10.2
>From 538208594a1af8b5539d83976e8161b46ea0e40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hert...@debian.org> Date: Mon, 14 Nov 2016 11:51:50 +0100 Subject: [PATCH 2/2] dpkg-shlibdeps: improve logic to identify package owning a library With the introduction of merged-/usr, we have libraries in that are stored in /usr/lib but that dpkg knows under /lib. This breaks some of the initial assumptions made in dpkg-shlibdeps. We now scan all possible paths for a given library (instead of trying to guessing which one is the canonical one) and whenever we find a match in the dpkg database, we also associate the package for the associated realpath(). That way when a library is not properly identified, we can fallback on looking if its realpath is known and be confident that if the library was packaged, we did identify it correctly. Closes: #843073 --- scripts/dpkg-shlibdeps.pl | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/scripts/dpkg-shlibdeps.pl b/scripts/dpkg-shlibdeps.pl index 3204026..f279f58 100755 --- a/scripts/dpkg-shlibdeps.pl +++ b/scripts/dpkg-shlibdeps.pl @@ -6,7 +6,7 @@ # Copyright © 2000 Wichert Akkerman # Copyright © 2006 Frank Lichtenheld # Copyright © 2006-2010,2012-2015 Guillem Jover <guil...@debian.org> -# Copyright © 2007 Raphaël Hertzog +# Copyright © 2007,2016 Raphaël Hertzog # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -35,7 +35,7 @@ use Dpkg::Util qw(:list); use Dpkg::Path qw(relative_to_pkg_root guess_pkg_root_dir check_files_are_the_same get_control_path); use Dpkg::Version; -use Dpkg::Shlibs qw(find_library get_library_paths); +use Dpkg::Shlibs qw(find_library_locations get_library_paths); use Dpkg::Shlibs::Objdump; use Dpkg::Shlibs::SymbolFile; use Dpkg::Substvars; @@ -192,8 +192,8 @@ foreach my $file (keys %exec) { my %soname_notfound; my %alt_soname; foreach my $soname (@sonames) { - my $lib = my_find_library($soname, $obj->{RPATH}, $obj->{format}, $file); - unless (defined $lib) { + my @locations = my_find_library($soname, $obj->{RPATH}, $obj->{format}, $file); + unless (scalar(@locations)) { $soname_notfound{$soname} = 1; $global_soname_notfound{$soname} = 1; my $msg = g_("couldn't find library %s needed by %s (ELF " . @@ -206,12 +206,14 @@ foreach my $file (keys %exec) { } next; } - $libfiles{$lib} = $soname; - my $reallib = realpath($lib); - if ($reallib ne $lib) { - $altlibfiles{$reallib} = $soname; - } - print "Library $soname found in $lib\n" if $debug; + foreach my $lib (@locations) { + $libfiles{$lib} = $soname; + my $reallib = realpath($lib); + if ($reallib ne $lib) { + $altlibfiles{$reallib} = $soname; + } + print "Library $soname found in $lib\n" if $debug; + } } my $file2pkg = find_packages(keys %libfiles, keys %altlibfiles); my $symfile = Dpkg::Shlibs::SymbolFile->new(); @@ -830,17 +832,14 @@ sub my_find_library { foreach my $builddir (@builddirs) { next if defined($dir_checked{$builddir}); next if ignore_pkgdir($builddir); - $file = find_library($lib, \@RPATH, $format, $builddir); - return $file if defined($file); + my @locations = find_library_locations($lib, \@RPATH, $format, $builddir); + return @locations if scalar(@locations); $dir_checked{$builddir} = 1; } # Fallback in the root directory if we have not found what we were # looking for in the packages - $file = find_library($lib, \@RPATH, $format, ''); - return $file if defined($file); - - return; + return find_library_locations($lib, \@RPATH, $format, ''); } my %cached_pkgmatch = (); @@ -879,7 +878,9 @@ sub find_packages { or syserr(g_('write diversion info to stderr')); } elsif (m/^([-a-z0-9+.:, ]+): (\/.*)$/) { my ($pkgs, $path) = ($1, $2); + my $realpath = realpath($path); $cached_pkgmatch{$path} = $pkgmatch->{$path} = [ split /, /, $pkgs ]; + $cached_pkgmatch{$realpath} = $pkgmatch->{$realpath} = [ split /, /, $pkgs ]; } else { warning(g_("unknown output from dpkg --search: '%s'"), $_); } -- 2.10.2