runone: +--disable-plugin=root_cache
[massrebuild.git] / dtneededsize
1 #! /usr/bin/perl
2 use strict;
3 use warnings;
4 use File::Basename qw(&dirname);
5 use File::Find;
6 use Data::Dumper;
7
8 $|=1;
9 sub readfile {
10   my($fname)=@_;
11   local *F;
12   open F,"$fname" or die $fname;
13   local $/=undef();
14   defined(my $r=<F>) or die $fname;
15   close F or die $fname;
16   return $r;
17 }
18
19 my %D;
20 # ==> build/Cadence-1.0.0-0.12.20200504git5787908.fc33.src.rpm.dtneeded <==
21 # /usr/lib/debug/.dwz/Cadence isdwzcommon 479079 NA
22 # /usr/bin/cadence-jackmeter /usr/lib/debug/.dwz/Cadence 717792 1329040
23 # /usr/bin/cadence-xycontroller /usr/lib/debug/.dwz/Cadence 1763616 2369832
24 # ==> build/CVector-1.0.3.1-21.fc33.src.rpm.dtneeded <==
25 # /usr/lib64/libCVector-1.0.3.so.2.0.0 nodwzcommon 28088 28896
26 for my $dtneededfn (glob "build/*.dtneeded") {
27   local *F;
28   open F,$dtneededfn or die "$dtneededfn: $1";
29   local $_;
30   while (<F>) {
31     chomp;
32     my($fn,$dwzcommon,$dwzsize,$dtsize)=/^(\S+) (\S+) (\S+) (\S+)$/ or die "$dtneededfn: $_";
33     die if $dwzcommon eq "isdwzcommon" && $dtsize ne "NA";
34     my $ref=\$D{$fn};
35     if ($$ref) {
36       die if $dwzcommon eq "isdwzcommon";
37       $$ref=[];
38     } else {
39       $$ref=[$dwzcommon,$dwzsize,$dtsize];
40     }
41   }
42   close F or die "close $dtneededfn: $1";
43 }
44
45 chdir "dtneeded.out" or die "dtneeded.out: $!";
46
47 my %F;
48 my %SONAME;
49 my @DEBUG;
50 my %SYMLINK;
51 find {
52   "no_chdir"=>1,
53   "wanted"=>sub {
54     die $File::Find::dir if $File::Find::dir=~m{/$};
55     my $binfn=$File::Find::name;
56     if (-l $binfn) {
57       my $target=readlink $binfn or die $binfn;
58       $binfn=~s{^[.]}{};
59       my $final;
60       if ($target=~m{^/}) {
61         $final=$target;
62 #warn "$binfn,target=rel=$$ref\n";
63       } else {
64         my $base=dirname(".$binfn");
65         my $abs=File::Spec->rel2abs($target,$base);
66         $final="/".File::Spec->abs2rel($abs);
67 #warn "$binfn,base=$base,target=$target,abs=$abs,rel=$$ref\n";
68       }
69       1 while $final=~s{/[^/]+/[.][.]/}{/};
70       1 while $final=~s{/[^/]+/[.][.]$}{};
71       if ($final=~m{/[.][.]}) {
72         warn "$binfn,target=$target,final=$final\n";
73         return;
74       }
75       my $ref=\$SYMLINK{$binfn};
76       die if $$ref;
77       $$ref=$final;
78       return;
79     }
80     return if !-f $binfn;
81     die $binfn if $binfn!~m{^[.]/};
82     my $bin=readfile $binfn;
83     $binfn=~s{^[.]}{} or die;
84     my $rpath=($bin=~m{^.*\Q(R\E(?:UN)?\QPATH)\E\s*Library r(?:un)?path: \Q[\E(.*)\Q]\E$}m)[0];
85     if ($rpath) {
86       my $dirname=$File::Find::dir;
87       die if $dirname!~s{^[.]/}{/};
88       $rpath=~s{\$ORIGIN}{$dirname}g;
89     }
90     my $soname=($bin=~m{^.*\Q(SONAME)\E\s*Library soname: \Q[\E(.*)\Q]\E$}m)[0];
91     my $h={
92       "binfn"=>$binfn,
93       "needed"=>[$bin=~m{^\s*0x0000000000000001\s*\Q(NEEDED)\E\s*\QShared library: [\E(.*)\Q]\E$}gm],
94     };
95     $h->{"rpath"}=$rpath if $rpath;
96     $F{$binfn}=$h;
97 #warn "$binfn=".Dumper($h)."\n" if $binfn=~/libc.so.6/;
98 #    my $total=keys %F; warn "$total...\n" if 0==$total%1000;
99     if ($soname) {
100       my $sonamefn=$File::Find::dir."/".$soname;
101       $sonamefn=~s{^[.]/}{/} or die $sonamefn;
102       my $ref=\$SONAME{$sonamefn};
103 #      warn "soname=<$sonamefn> <$binfn> vs. <".$$ref->{"binfn"}.">\n" if $$ref;
104       $$ref=$h;
105     }
106     push @DEBUG,$binfn if $bin=~m{ \Q(DEBUG) \E };
107   },
108 },".";
109
110 #while (my($src,$target)=each %SYMLINK) {
111 #  die "$src->$target" if exists $SYMLINK{$target};
112 #}
113
114 my $dwzsizeall=0;
115 my $dtsizeall=0;
116 my $computed=0;
117 BINFN: for my $binfn (@DEBUG) {
118 #  warn "$binfn...\n".Dumper([sort @{$F{$binfn}{"needed"}}]);
119   die $binfn if exists $SYMLINK{$binfn};
120   my @l=$binfn;
121   my %l=($binfn=>1);
122   while (@l) {
123     my $l=shift @l;
124     my $h=$F{$l};
125     for my $needed (@{$h->{"needed"}}) {
126       my $found;
127       if ($needed=~m{^/}) {
128         $needed=$SYMLINK{$needed} while exists $SYMLINK{$needed};
129         $found=$needed;
130       } else {
131 #       die "$binfn: $l: $needed" if $needed=~m{/};
132         my @rpath;
133         my $rpath=$h->{"rpath"};
134         push @rpath,split /:/,$rpath if $rpath;
135         push @rpath,qw(/lib64 /usr/lib64);
136         for my $rpath (@rpath) {
137           if ($rpath!~m{^/}) {
138             warn "$binfn: $l: $rpath";
139             next;
140           }
141           my $fn="$rpath/$needed";
142           $fn=$SYMLINK{$fn} while exists $SYMLINK{$fn};
143           next if !$SONAME{$fn};
144           $found=$fn;
145           last;
146         }
147         warn "$binfn: $l: $needed not found; rpath=".join(":",@rpath)."\n" if !$found;
148       }
149       push @l,$found if $found&&!$l{$found}++;
150     }
151   }
152 #warn Dumper $binfn,\%l;
153   my $dwzsizetot=0;
154   my $dtsizetot=0;
155   my %dwzcommons;
156   for my $l (keys(%l)) {
157     my $ref=$D{$l};
158     if (!defined $ref) {
159       warn "$binfn: $l: missing\n";
160       next BINFN;
161     }
162     if (0==@$ref) {
163       warn "$binfn: $l: ambiguous\n";
164       next BINFN;
165     }
166     my $dtsize=$ref->[2];
167     die if !defined $dtsize;
168     $dtsizetot+=$dtsize;
169     my $dwzsize=$ref->[1];
170     die if !defined $dwzsize;
171     $dwzsizetot+=$dwzsize;
172     $computed++;
173     my $dwzcommon=$ref->[0];
174     next if $dwzcommon eq "nodwzcommon";
175     die if $dwzcommon eq "isdwzcommon";
176     next if $dwzcommons{$dwzcommon}++;
177     my $dwzcommonref=$D{$dwzcommon};
178     die if !$dwzcommonref;
179     die if $dwzcommonref->[0] ne "isdwzcommon";
180     die if $dwzcommonref->[2] ne "NA";
181     my $dwzcommonsize=$dwzcommonref->[1];
182     $dwzsizetot+=$dwzcommonsize;
183   }
184   print "$binfn: dwzsizetot=$dwzsizetot dtsizetot=$dtsizetot\n";
185 warn "$binfn: ".Dumper(\%dwzcommons);
186   $dwzsizeall+=$dwzsizetot;
187   $dtsizeall+=$dtsizetot;
188 #  warn "$binfn done\n".Dumper([sort keys(%l)]);
189 }
190 print "dwzsizeall=$dwzsizeall dtsizeall=$dtsizeall =".$dwzsizeall/$dtsizeall."\n";
191 print "computed=$computed of DEBUG=".(0+@DEBUG)."\n";