summaryrefslogtreecommitdiff
path: root/tools/apbuild/scandeps
diff options
context:
space:
mode:
Diffstat (limited to 'tools/apbuild/scandeps')
-rwxr-xr-xtools/apbuild/scandeps137
1 files changed, 137 insertions, 0 deletions
diff --git a/tools/apbuild/scandeps b/tools/apbuild/scandeps
new file mode 100755
index 00000000..7d057129
--- /dev/null
+++ b/tools/apbuild/scandeps
@@ -0,0 +1,137 @@
+#!/usr/bin/env perl
+use strict;
+use IPC::Open2;
+
+if ($ARGV[0] eq '--version') {
+ print "scandeps version 1.0\n";
+ print "Copright (c) 2005 Hongli Lai\n";
+ print "Licensed under the GNU General Public License v2.\n";
+ exit;
+} elsif ($ARGV[0] eq '--help') {
+ print "Usage: scandeps [FILES...]\n";
+ print "This script scans ELF binaries' library dependancies and prints a nice report\n" .
+ "of the dependancies.\n";
+ exit;
+}
+
+
+# First, generate a list of binaries. Either scan user-specified files,
+# or scan all files in the current directory (including subfolders).
+my @files;
+
+if (@ARGV > 0) {
+ # Scan user-specified files
+ @files = @ARGV;
+} else {
+ # Scan directory recursively
+ @files = scandir(".");
+}
+
+# Now get the dependancies for all binaries
+# %fileDeps: hash which contains a list of dependancies. The filename is the key.
+# %depFiles: hash which contains a list of files. The dependancy is the key.
+my (%fileDeps, %depFiles);
+getdeps(\%fileDeps, \%depFiles, \@files);
+
+print "Common dependancies:\n";
+foreach my $dep (keys %depFiles) {
+ if (@{$depFiles{$dep}} == @files) {
+ print " $dep\n";
+ }
+}
+print "\n";
+
+print "All dependancies:\n";
+my @keys = keys %depFiles;
+@keys = sort { @{$depFiles{$b}} - @{$depFiles{$a}} } @keys;
+foreach my $dep (@keys) {
+ my $num = scalar(@{$depFiles{$dep}});
+ my $word = ($num > 1) ? "files" : "file";
+ printf " %-40s (used by %3d $word)\n", $dep, $num;
+}
+
+print "\n";
+print "Dependancies and associated binaries:\n";
+foreach my $dep (@keys) {
+ print " $dep:\n";
+ if (@{$depFiles{$dep}} == @files) {
+ print " All files depend on this library.\n";
+ } else {
+ foreach my $file (@{$depFiles{$dep}}) {
+ print " $file\n";
+ }
+ }
+ print "\n";
+}
+
+
+##################################
+
+sub fatal {
+ print STDERR $_[0];
+ exit 1;
+}
+
+sub isELF {
+ my ($f, $data);
+
+ if (!open($f, $_[0])) {
+ print STDERR "Warning: cannot open file '$_[0]' for reading.\n";
+ return 0;
+ }
+
+ binmode $f;
+ sysread $f, $data, 4;
+ close $f;
+ return $data eq "\177ELF";
+}
+
+sub scandir {
+ my $d;
+
+ if (!opendir($d, $_[0])) {
+ print STDERR "Warning: cannot open directory '$_[0]' for reading.\n";
+ return;
+ }
+
+ my @files;
+ foreach my $file (readdir($d)) {
+ next if ($file eq "." || $file eq "..");
+
+ $file = "$_[0]/$file";
+ if (-d $file) {
+ # Recurse into subdirectory
+ push @files, scandir("$file");
+
+ } elsif (-f $file && -x $file && isELF($file)) {
+ push @files, $file;
+ }
+ }
+ closedir($d);
+ return @files;
+}
+
+sub getdeps {
+ my ($fileDeps, $depFiles, $files) = @_;
+ my ($r, $w);
+ if (!open2($r, $w, 'objdump', '-p', @{$files})) {
+ fatal("Cannot communicate with objdump.\n");
+ }
+ close $w;
+
+ my $currentFile;
+ foreach my $line (<$r>) {
+ if ($line =~ /^(.+):[ \t]+file format /) {
+ $currentFile = $1;
+ $currentFile =~ s/^.\///;
+
+ } elsif ($line =~ /NEEDED[ \t]+(.+)$/) {
+ $fileDeps->{$currentFile} = [] if (!exists $fileDeps->{$currentFile});
+ push @{$fileDeps->{$currentFile}}, $1;
+
+ $depFiles->{$1} = [] if (!exists $depFiles->{$1});
+ push @{$depFiles->{$1}}, $currentFile;
+ }
+ }
+ close $r;
+}