dtneededsize: ldd done
[massrebuild.git] / dtneededsize
old mode 100644 (file)
new mode 100755 (executable)
index 1354bb8..9cbb467
@@ -1,7 +1,88 @@
-#! /bin/bash
-cd dtneeded.out || exit 1
-for bin in $(grep -rl ' (DEBUG) ' .);do
-  sed -n 's/^ *0x0000000000000001 *(NEEDED) *Shared library: \[\(.*\)\]$/\1/p' <$bin
-  rpath="$(sed -n 's/^.*(R\(\|UN\)PATH) *Library r\(\|un\)path: \[\(.*\)\]$/\1/p' <$bin):."
-  rpath="$(echo "$rpath"|sed 's#[$]ORIGIN#'"$(dirname $bin)"'#g')"
-done
+#! /usr/bin/perl
+use strict;
+use warnings;
+use File::Basename qw(&dirname);
+use File::Find;
+use Data::Dumper;
+
+$|=1;
+sub readfile {
+  my($fname)=@_;
+  local *F;
+  open F,"$fname" or die $fname;
+  local $/=undef();
+  defined(my $r=<F>) or die $fname;
+  close F or die $fname;
+  return $r;
+}
+
+chdir "dtneeded.out" or die "dtneeded.out: $!";
+
+my %F;
+my %SONAME;
+my @DEBUG;
+find {
+  "no_chdir"=>1,
+  "wanted"=>sub {
+    die $File::Find::dir if $File::Find::dir=~m{/$};
+    my $binfn=$File::Find::name;
+    return if !-f $binfn;
+    die $binfn if $binfn!~m{^[.]/};
+    my $bin=readfile $binfn;
+    my $rpath=($bin=~m{^.*\Q(R\E(?:UN)?\QPATH)\E\s*Library r(?:un)?path: \Q[\E(.*)\Q]\E$}m)[0];
+    if ($rpath) {
+      my $dirname=$File::Find::dir;
+      die if $dirname!~s{^[.]/}{/};
+      $rpath=~s{\$ORIGIN}{$dirname}g;
+    }
+    my $soname=($bin=~m{^.*\Q(SONAME)\E\s*Library soname: \Q[\E(.*)\Q]\E$}m)[0];
+    my $h={
+      "binfn"=>$binfn,
+      "needed"=>[$bin=~m{^\s*0x0000000000000001\s*\Q(NEEDED)\E\s*\QShared library: [\E(.*)\Q]\E$}gm],
+    };
+    $h->{"rpath"}=$rpath if $rpath;
+    $F{$binfn}=$h;
+#    my $total=keys %F; warn "$total...\n" if 0==$total%1000;
+    if ($soname) {
+      my $ref=\$SONAME{$File::Find::dir."/".$soname};
+#      warn "soname=<$soname> <$binfn> vs. <".$$ref->{"binfn"}.">\n" if $$ref;
+      $$ref=$h;
+    }
+    push @DEBUG,$binfn if $bin=~m{ \Q(DEBUG) \E };
+  },
+},".";
+
+for my $binfn (@DEBUG) {
+#  warn "$binfn...\n".Dumper([sort @{$F{$binfn}{"needed"}}]);
+  my @l=$binfn;
+  my %l=($binfn=>1);
+  while (@l) {
+    my $l=shift @l;
+    my $h=$F{$l};
+    for my $needed (@{$h->{"needed"}}) {
+      my $found;
+      if ($needed=~m{^/}) {
+       $found=$needed;
+      } else {
+#      die "$binfn: $l: $needed" if $needed=~m{/};
+       my @rpath;
+       my $rpath=$h->{"rpath"};
+       push @rpath,split /:/,$rpath if $rpath;
+       push @rpath,qw(/lib64 /usr/lib64);
+       for my $rpath (@rpath) {
+         if ($rpath!~m{^/}) {
+           warn "$binfn: $l: $rpath";
+           next;
+         }
+         my $fn=".$rpath/$needed";
+         next if !$SONAME{$fn};
+         $found=$fn;
+         last;
+       }
+       warn "$binfn: $l: $needed not found; rpath=".join(":",@rpath)."\n" if !$found;
+      }
+      push @l,$found if $found&&!$l{$found}++;
+    }
+  }
+#  warn "$binfn done\n".Dumper([sort keys(%l)]);
+}