#! /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=) 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)]); }