~ximion/listaller/master

« back to all changes in this revision

Viewing changes to contrib/apbuild/scandeps

  • Committer: Matthias Klumpp
  • Date: 2011-07-12 11:51:32 UTC
  • mfrom: (0.4.6)
  • Revision ID: git-v1:40deffc428db6704895e2a37de271e46234ef169
Merge branch 'master' of /home/matthias/Development/Listaller/liextrajunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env perl
 
2
use strict;
 
3
use IPC::Open2;
 
4
 
 
5
if ($ARGV[0] eq '--version') {
 
6
        print "scandeps version 1.0\n";
 
7
        print "Copright (c) 2005 Hongli Lai\n";
 
8
        print "Licensed under the GNU General Public License v3.\n";
 
9
        exit;
 
10
} elsif ($ARGV[0] eq '--help') {
 
11
        print "Usage: scandeps [FILES...]\n";
 
12
        print "This script scans ELF binaries' library dependancies and prints a nice report\n" .
 
13
                "of the dependancies.\n";
 
14
        exit;
 
15
}
 
16
 
 
17
 
 
18
# First, generate a list of binaries. Either scan user-specified files,
 
19
# or scan all files in the current directory (including subfolders).
 
20
my @files;
 
21
 
 
22
if (@ARGV > 0) {
 
23
        # Scan user-specified files
 
24
        @files = @ARGV;
 
25
} else {
 
26
        # Scan directory recursively
 
27
        @files = scandir(".");
 
28
}
 
29
 
 
30
# Now get the dependancies for all binaries
 
31
# %fileDeps: hash which contains a list of dependancies. The filename is the key.
 
32
# %depFiles: hash which contains a list of files. The dependancy is the key.
 
33
my (%fileDeps, %depFiles);
 
34
getdeps(\%fileDeps, \%depFiles, \@files);
 
35
 
 
36
print "Common dependancies:\n";
 
37
foreach my $dep (keys %depFiles) {
 
38
        if (@{$depFiles{$dep}} == @files) {
 
39
                print " $dep\n";
 
40
        }
 
41
}
 
42
print "\n";
 
43
 
 
44
print "All dependancies:\n";
 
45
my @keys = keys %depFiles;
 
46
@keys = sort { @{$depFiles{$b}} - @{$depFiles{$a}} } @keys;
 
47
foreach my $dep (@keys) {
 
48
        my $num = scalar(@{$depFiles{$dep}});
 
49
        my $word = ($num > 1) ? "files" : "file";
 
50
        printf " %-40s (used by %3d $word)\n", $dep, $num;
 
51
}
 
52
 
 
53
print "\n";
 
54
print "Dependancies and associated binaries:\n";
 
55
foreach my $dep (@keys) {
 
56
        print " $dep:\n";
 
57
        if (@{$depFiles{$dep}} == @files) {
 
58
                print "    All files depend on this library.\n";
 
59
        } else {
 
60
                foreach my $file (@{$depFiles{$dep}}) {
 
61
                        print "    $file\n";
 
62
                }
 
63
        }
 
64
        print "\n";
 
65
}
 
66
 
 
67
 
 
68
##################################
 
69
 
 
70
sub fatal {
 
71
        print STDERR $_[0];
 
72
        exit 1;
 
73
}
 
74
 
 
75
sub isELF {
 
76
        my ($f, $data);
 
77
 
 
78
        if (!open($f, $_[0])) {
 
79
                print STDERR "Warning: cannot open file '$_[0]' for reading.\n";
 
80
                return 0;
 
81
        }
 
82
 
 
83
        binmode $f;
 
84
        sysread $f, $data, 4;
 
85
        close $f;
 
86
        return $data eq "\177ELF";
 
87
}
 
88
 
 
89
sub scandir {
 
90
        my $d;
 
91
 
 
92
        if (!opendir($d, $_[0])) {
 
93
                print STDERR "Warning: cannot open directory '$_[0]' for reading.\n";
 
94
                return;
 
95
        }
 
96
 
 
97
        my @files;
 
98
        foreach my $file (readdir($d)) {
 
99
                next if ($file eq "." || $file eq "..");
 
100
 
 
101
                $file = "$_[0]/$file";
 
102
                if (-d $file) {
 
103
                        # Recurse into subdirectory
 
104
                        push @files, scandir("$file");
 
105
 
 
106
                } elsif (-f $file && -x $file && isELF($file)) {
 
107
                        push @files, $file;
 
108
                }
 
109
        }
 
110
        closedir($d);
 
111
        return @files;
 
112
}
 
113
 
 
114
sub getdeps {
 
115
        my ($fileDeps, $depFiles, $files) = @_;
 
116
        my ($r, $w);
 
117
        if (!open2($r, $w, 'objdump', '-p', @{$files})) {
 
118
                fatal("Cannot communicate with objdump.\n");
 
119
        }
 
120
        close $w;
 
121
 
 
122
        my $currentFile;
 
123
        foreach my $line (<$r>) {
 
124
                if ($line =~ /^(.+):[ \t]+file format /) {
 
125
                        $currentFile = $1;
 
126
                        $currentFile =~ s/^.\///;
 
127
 
 
128
                } elsif ($line =~ /NEEDED[ \t]+(.+)$/) {
 
129
                        $fileDeps->{$currentFile} = [] if (!exists $fileDeps->{$currentFile});
 
130
                        push @{$fileDeps->{$currentFile}}, $1;
 
131
 
 
132
                        $depFiles->{$1} = [] if (!exists $depFiles->{$1});
 
133
                        push @{$depFiles->{$1}}, $currentFile;
 
134
                }
 
135
        }
 
136
        close $r;
 
137
}