my %F;
my %SONAME;
my @DEBUG;
-my %SYMLINK;
find {
"no_chdir"=>1,
"wanted"=>sub {
die $File::Find::dir if $File::Find::dir=~m{/$};
my $binfn=$File::Find::name;
- if (-l $binfn) {
- my $target=readlink $binfn or die $binfn;
- $binfn=~s{^[.]}{};
- my $final;
- if ($target=~m{^/}) {
- $final=$target;
-#warn "$binfn,target=rel=$$ref\n";
- } else {
- my $base=dirname(".$binfn");
- my $abs=File::Spec->rel2abs($target,$base);
- $final="/".File::Spec->abs2rel($abs);
-#warn "$binfn,base=$base,target=$target,abs=$abs,rel=$$ref\n";
- }
- 1 while $final=~s{/[^/]+/[.][.]/}{/};
- 1 while $final=~s{/[^/]+/[.][.]$}{};
- if ($final=~m{/[.][.]}) {
- warn "$binfn,target=$target,final=$final\n";
- return;
- }
- my $ref=\$SYMLINK{$binfn};
- die if $$ref;
- $$ref=$final;
- return;
- }
- return if !-f $binfn;
+ return if $binfn eq ".";
die $binfn if $binfn!~m{^[.]/};
+ return if -l $binfn;
+ return if !-f $binfn;
my $bin=readfile $binfn;
$binfn=~s{^[.]}{} or die;
+ return if $bin=~m{^\s*0x0{8}\s+\Q(NULL)\E\s+0x0$}m;
+ return if $bin!~m{^\s*0x0{16}\s+\Q(NULL)\E\s+0x0$}m;
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;
if ($soname) {
my $sonamefn=$File::Find::dir."/".$soname;
$sonamefn=~s{^[.]/}{/} or die $sonamefn;
- my $ref=\$SONAME{$sonamefn};
+ my $ref=\$SONAME{$binfn};
# warn "soname=<$sonamefn> <$binfn> vs. <".$$ref->{"binfn"}.">\n" if $$ref;
+#warn "soname=<$sonamefn> <$binfn>" if $soname=~/libc/;
$$ref=$h;
}
push @DEBUG,$binfn if $bin=~m{ \Q(DEBUG) \E };
},
},".";
-#while (my($src,$target)=each %SYMLINK) {
-# die "$src->$target" if exists $SYMLINK{$target};
-#}
+sub resolve($) {
+ my($binfn)=@_;
+ die if $binfn!~m{^/};
+ return $binfn if !-l ".$binfn";
+ $binfn=".$binfn";
+ my $target=readlink $binfn or die $binfn;
+ $binfn=~s{^[.]}{};
+ my $final;
+ if ($target=~m{^/}) {
+ $final=$target;
+#warn "$binfn,target=final=$final\n";
+ } else {
+ my $base=dirname(".$binfn");
+ my $abs=File::Spec->rel2abs($target,$base);
+ $final="/".File::Spec->abs2rel($abs);
+#warn "$binfn,base=$base,target=$target,abs=$abs,final=$final\n";
+ }
+ 1 while $final=~s{/[^/]+/[.][.]/}{/};
+ 1 while $final=~s{/[^/]+/[.][.]$}{};
+ if ($final=~m{/[.][.]}) {
+ warn "$binfn,target=$target,final=$final\n";
+ return;
+ }
+#warn "$binfn,final=$final\n";
+ return &resolve($final);
+}
my $dwzsizeall=0;
my $dwzsizeduplall=0;
my @ratioall;
my @ratioduplall;
my $computed=0;
+#@DEBUG="/usr/bin/elfedit";
BINFN: for my $binfn (@DEBUG) {
# warn "$binfn...\n".Dumper([sort @{$F{$binfn}{"needed"}}]);
- die $binfn if exists $SYMLINK{$binfn};
+ die $binfn if -l ".$binfn";
my @l=$binfn;
my %l=($binfn=>1);
while (@l) {
my $l=shift @l;
my $h=$F{$l};
+#warn "$binfn: $l: ".Dumper($h);
for my $needed (@{$h->{"needed"}}) {
my $found;
if ($needed=~m{^/}) {
- $needed=$SYMLINK{$needed} while exists $SYMLINK{$needed};
- $found=$needed;
+ $found=resolve $needed;
} else {
# die "$binfn: $l: $needed" if $needed=~m{/};
my @rpath;
next;
}
my $fn="$rpath/$needed";
- $fn=$SYMLINK{$fn} while exists $SYMLINK{$fn};
+#warn "A:$fn\n" if $fn=~/libc/;
+ $fn=resolve $fn;
+#warn "B:$fn\n" if $fn=~/libc/;
next if !$SONAME{$fn};
+#warn "C:$fn\n" if $fn=~/libc/;
$found=$fn;
last;
}
my $dwzsizedupltot=0;
my $dtsizetot=0;
my %dwzcommons;
+#warn "$binfn: ".Dumper(\%l);
for my $l (keys(%l)) {
my $ref=$D{$l};
if (!defined $ref) {
die if !defined $dwzsize;
$dwzsizetot+=$dwzsize;
$dwzsizedupltot+=$dwzsize;
- $computed++;
my $dwzcommon=$ref->[0];
next if $dwzcommon eq "nodwzcommon";
die if $dwzcommon eq "isdwzcommon";
$dwzsizedupltot+=$dwzcommonsize;
}
print "$binfn: dwzsizetot=$dwzsizetot dtsizetot=$dtsizetot\n";
-warn "$binfn: ".Dumper(\%dwzcommons);
+#warn "$binfn: ".Dumper(\%dwzcommons);
+ $computed++;
$dwzsizeall+=$dwzsizetot;
$dwzsizeduplall+=$dwzsizedupltot;
$dtsizeall+=$dtsizetot;
+warn "ratio ".$dwzsizetot /$dtsizetot." dwzsizetot=$dwzsizetot dtsizetot=$dtsizetot: $binfn\n";
push @ratioall ,$dwzsizetot /$dtsizetot;
push @ratioduplall,$dwzsizedupltot/$dtsizetot;
# warn "$binfn done\n".Dumper([sort keys(%l)]);