[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Objdump patch for dpkg-shlibdeps



This patch does two things, one more successfully/completely than the
other:

 - Use objdump instead of ldd, producing fewer bogus warnings/errors. 
   This part works fine, and shows no regressions that I could find.

 - Handle shared libraries which are in a package produced by this
   source which are not yet installed.  I haven't quite got it working
   in all cases yet.

Comments?

Dan

/--------------------------------\  /--------------------------------\
|       Daniel Jacobowitz        |__|     CMU, CS class of 2002      |
|   Debian GNU/Linux Developer    __   Part-Time Systems Programmer  |
|         dan@debian.org         |  |        drow@cs.cmu.edu         |
\--------------------------------/  \--------------------------------/
--- /usr/src/dpkg/dpkg-1.4.1/scripts/dpkg-shlibdeps.pl	Sun Nov  1 11:07:43 1998
+++ /usr/bin/dpkg-shlibdeps	Sun Dec  6 19:24:59 1998
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 
-$dpkglibdir= ".";
-$version= '1.3.6'; # This line modified by Makefile
+$dpkglibdir= "/usr/lib/dpkg";
+$version= '1.4.1'; # This line modified by Makefile
 
 use POSIX;
 use POSIX qw(:errno_h :signal_h);
@@ -88,40 +88,79 @@
 
 for ($i=0;$i<=$#exec;$i++) {
     if (!isbin ($exec[$i])) { next; }
-    defined($c= open(P,"-|")) || syserr("cannot fork for ldd");
-    if (!$c) { exec("ldd","--",$exec[$i]); syserr("cannot exec ldd"); }
-    $nthisldd=0;
+    defined($c= open(P,"-|")) || syserr("cannot fork for objdump");
+    if (!$c) { exec("objdump","-p","--",$exec[$i]); syserr("cannot exec objdump"); }
     while (<P>) {
-    	chomp;
-	if (m,^\s+(\S+)\s+\=\>\s+\1$,) {
-	    # shared libraries depend on themselves (unsure why)
-	    # Only under old ld.so
-	    $nthisldd++;
-	} elsif (m,\s+statically linked(\s+\(ELF\))?$,) {
-	    $nthisldd++;
-	} elsif (m,^\s+(\S+)\.so\.(\S+)\s+=>\s+(/\S+)(\s+\(0x.+\))?$,) {
-	    push(@libname,$1); push(@libsoname,$2); push(@libpath,$3);
-	    push(@libf,$execf[$i]);
-	    push(@libpaths,$3) if !$libpathadded{$3}++;
-	    $nthisldd++;
-	} else {
-	    &warn("unknown output from ldd on \`$exec[$i]': \`$_'");
-	}
+        chomp;
+        if (m,^\s*NEEDED\s+(\S+)\.so\.(\S+)$,) {
+            push(@libname,$1); push(@libsoname,$2);
+            push(@libf,$execf[$i]);
+            push(@libfiles,"$1.so.$2");
+        }
+    }
+    close(P); $? && subprocerr("objdump on \`$exec[$i]'");
+}
+
+# Now: See if it is in this package.  See if it is in any other package.
+sub searchdir {
+    my $dir = shift;
+    if(opendir(DIR, $dir)) {
+        my @dirents = readdir(DIR);
+        closedir(DIR);
+        for (@dirents) {
+            if ( -f "$dir/$_/DEBIAN/shlibs" ) {
+                push(@curshlibs, "$dir/$_/DEBIAN/shlibs");
+                last;
+            } elsif ( $_ !~ /^\./ && -d "$dir/$_" ) {
+                &searchdir("$dir/$_");
+            }
+        }
+    }
+}
+
+$searchdir = $exec[0];
+$curpackdir = "debian/tmp";
+do { $searchdir =~ s,/[^/]*$,,; } while($searchdir =~ m,/, && ! -d "$searchdir/DEBIAN");
+if ($searchdir =~ m,/,) {
+    $curpackdir = $searchdir;
+    $searchdir =~ s,/[^/]*,,;
+    &searchdir($searchdir);
+}
+
+if ($#curshlibs >= 0) {
+    PRELIB: for ($i=0;$i<=$#libname;$i++) {
+        for my $shlibsfile (@curshlibs) {
+            if(scanshlibsfile($shlibsfile, $libname[$i], $libsoname[$i], $libf[$i])) {
+                splice(@libname, $i, 1);
+                splice(@libsoname, $i, 1);
+                splice(@libf, $i, 1);
+                splice(@libfiles, $i, 1);
+                $i--;
+                next PRELIB;
+            }
+        }
+        if(scanshlibsfile($shlibslocal,$libname[$i],$libsoname[$i],$libf[$i]) 
+          || scanshlibsfile($shlibsoverride,$libname[$i],$libsoname[$i],$libf[$i])) {
+            splice(@libname, $i, 1);
+            splice(@libsoname, $i, 1);
+            splice(@libf, $i, 1);
+            splice(@libfiles, $i, 1);
+            $i--;
+            next PRELIB;
+        }
     }
-    close(P); $? && subprocerr("ldd on \`$exec[$i]'");
-    $nthisldd || &warn("ldd on \`$exec[$i]' gave nothing on standard output");
 }
 
-if ($#libpaths >= 0) {
-    grep(s/\[\?\*/\\$&/g, @libpaths);
+if ($#libfiles >= 0) {
+    grep(s/\[\?\*/\\$&/g, @libname);
     defined($c= open(P,"-|")) || syserr("cannot fork for dpkg --search");
-    if (!$c) { exec("dpkg","--search","--",@libpaths); syserr("cannot exec dpkg"); }
+    if (!$c) { exec("dpkg","--search","--",map {"*/$_"} @libfiles); syserr("cannot exec dpkg"); }
     while (<P>) {
        s/\n$//;
        if (m/^local diversion |^diversion by/) {
            &warn("diversions involved - output may be incorrect");
            print(STDERR " $_\n") || syserr("write diversion info to stderr");
-       } elsif (m=^(\S+(, \S+)*): (/.+)$=) {
+       } elsif (m=^(\S+(, \S+)*): /.+/([^/]+)$=) {
            $pathpackages{$+}= $1;
        } else {
            &warn("unknown output from dpkg --search: \`$_'");
@@ -131,13 +170,11 @@
 }
 
 LIB: for ($i=0;$i<=$#libname;$i++) {
-    scanshlibsfile($shlibslocal,$libname[$i],$libsoname[$i],$libf[$i]) && next;
-    scanshlibsfile($shlibsoverride,$libname[$i],$libsoname[$i],$libf[$i]) && next;
-    if (!defined($pathpackages{$libpath[$i]})) {
-        &warn("could not find any packages for $libpath[$i]".
+    if (!defined($pathpackages{$libfiles[$i]})) {
+        &warn("could not find any packages for $libfiles[$i]".
               " ($libname[$i].so.$libsoname[$i])");
     } else {
-        @packages= split(/, /,$pathpackages{$libpath[$i]});
+        @packages= split(/, /,$pathpackages{$libfiles[$i]});
         for $p (@packages) {
             scanshlibsfile("$shlibsppdir/$p$shlibsppext",
                            $libname[$i],$libsoname[$i],$libf[$i])
@@ -146,7 +183,7 @@
     }
     scanshlibsfile($shlibsdefault,$libname[$i],$libsoname[$i],$libf[$i]) && next;
     &warn("unable to find dependency information for ".
-          "shared library $libname[$i] (soname $libsoname[$i], path $libpath[$i], ".
+          "shared library $libname[$i] (soname $libsoname[$i], path $libfiles[$i], ".
           "dependency field $libf[$i])");
 }
 
@@ -167,6 +204,7 @@
             next;
         }
         next if $1 ne $ln || $2 ne $lsn;
+        return 1 if $fn eq "debian/$curpackdir/DEBIAN/shlibs";
         $da= $';
         for $dv (split(/,/,$da)) {
             $dv =~ s/^\s+//; $dv =~ s/\s+$//;

Reply to: