Make warnings go away.
[oweals/busybox.git] / examples / depmod.pl
1 #!/usr/bin/perl -w
2 # vi: set ts=4:
3 # Copyright (c) 2001 David Schleef <ds@schleef.org>
4 # Copyright (c) 2001 Erik Andersen <andersen@codepoet.org>
5 # Copyright (c) 2001 Stuart Hughes <seh@zee2.com>
6 # Copyright (c) 2002 Steven J. Hill <shill@broadcom.com>
7 # Copyright (c) 2006 Freescale Semiconductor, Inc <stuarth@freescale.com>
8 #
9 # History:
10 # March 2006: Stuart Hughes <stuarth@freescale.com>.
11 #             Significant updates, including implementing the '-F' option
12 #             and adding support for 2.6 kernels.
13
14 # This program is free software; you can redistribute it and/or modify it
15 # under the same terms as Perl itself.
16 use Getopt::Long;
17 use File::Find;
18 use strict;
19
20 # Set up some default values
21 my $kdir="";
22 my $basedir="";
23 my $kernel="";
24 my $kernelsyms="";
25 my $stdout=0;
26 my $verbose=0;
27 my $help=0;
28 my $nm = $ENV{'NM'} || "nm";
29
30 # more globals
31 my (@liblist) = ();
32 my $exp = {};
33 my $dep = {};
34 my $mod = {};
35
36 my $usage = <<TXT;
37 $0 -b basedir { -k <vmlinux> | -F <System.map> } [options]... 
38   Where:
39    -h --help         : Show this help screen
40    -b --basedir      : Modules base directory (e.g /lib/modules/<2.x.y>)
41    -k --kernel       : Kernel binary for the target (e.g. vmlinux)
42    -F --kernelsyms   : Kernel symbol file (e.g. System.map)
43    -n --stdout       : Write to stdout instead of <basedir>/modules.dep
44    -v --verbose      : Print out lots of debugging stuff
45 TXT
46
47 # get command-line options
48 GetOptions(
49         "help|h"         => \$help,
50         "basedir|b=s"    => \$basedir,
51         "kernel|k=s"     => \$kernel,
52         "kernelsyms|F=s" => \$kernelsyms,
53         "stdout|n"       => \$stdout,
54         "verbose|v"      => \$verbose,
55 );
56
57 die $usage if $help;
58 die $usage unless $basedir && ( $kernel || $kernelsyms );
59 die "can't use both -k and -F\n\n$usage" if $kernel && $kernelsyms;
60
61 # Strip any trailing or multiple slashes from basedir
62 $basedir =~ s-(/)\1+-/-g;
63
64 # The base directory should contain /lib/modules somewhere
65 if($basedir !~ m-/lib/modules-) {
66     warn "WARNING: base directory does not match ..../lib/modules\n";
67 }
68
69 # if no kernel version is contained in the basedir, try to find one
70 if($basedir !~ m-/lib/modules/\d\.\d-) {
71     opendir(BD, $basedir) or die "can't open basedir $basedir : $!\n";
72     foreach ( readdir(BD) ) {
73         next if /^\.\.?$/;
74         next unless -d "$basedir/$_";
75         warn "dir = $_\n" if $verbose;
76         if( /^\d\.\d/ ) {
77             $kdir = $_;
78             warn("Guessed module directory as $basedir/$kdir\n");
79             last;
80         }
81     }
82     closedir(BD);
83     die "Cannot find a kernel version under $basedir\n" unless $kdir;
84     $basedir = "$basedir/$kdir";
85 }
86
87 # Find the list of .o or .ko files living under $basedir
88 warn "**** Locating all modules\n" if $verbose;
89 find sub {
90     my $file;
91         if ( -f $_  && ! -d $_ ) {
92                 $file = $File::Find::name;
93                 if ( $file =~ /\.k?o$/ ) {
94                         push(@liblist, $file);
95                         warn "$file\n" if $verbose;
96                 }
97         }
98 }, $basedir;
99 warn "**** Finished locating modules\n" if $verbose;
100
101 foreach my $obj ( @liblist ){
102     # turn the input file name into a target tag name
103     my ($tgtname) = $obj =~ m-(/lib/modules/.*)$-;
104
105     warn "\nMODULE = $tgtname\n" if $verbose;
106
107     # get a list of symbols
108         my @output=`$nm $obj`;
109
110     build_ref_tables($tgtname, \@output, $exp, $dep);
111 }
112
113
114 # vmlinux is a special name that is only used to resolve symbols
115 my $tgtname = 'vmlinux';
116 my @output = $kernelsyms ? `cat $kernelsyms` : `$nm $kernel`;
117 warn "\nMODULE = $tgtname\n" if $verbose;
118 build_ref_tables($tgtname, \@output, $exp, $dep);
119
120 # resolve the dependencies for each module
121 # reduce dependencies: remove unresolvable and resolved from vmlinux/System.map
122 # remove duplicates
123 foreach my $module (keys %$dep) {
124     warn "reducing module: $module\n" if $verbose;
125     $mod->{$module} = {};
126     foreach (@{$dep->{$module}}) {
127         if( $exp->{$_} ) {
128             warn "resolved symbol $_ in file $exp->{$_}\n" if $verbose;
129             next if $exp->{$_} =~ /vmlinux/;
130             $mod->{$module}{$exp->{$_}} = 1;
131         } else {
132             warn "unresolved symbol $_ in file $module\n";
133         }
134     }
135 }
136
137 # figure out where the output should go
138 if ($stdout == 0) {
139     open(STDOUT, ">$basedir/modules.dep")
140                              or die "cannot open $basedir/modules.dep: $!";
141 }
142 my $kseries = $basedir =~ m,/2\.6\.[^/]*, ? '2.6' : '2.4';
143
144 foreach my $module ( keys %$mod ) {
145     if($kseries eq '2.4') {
146             print "$module:\t";
147             my @sorted = sort bydep keys %{$mod->{$module}};
148             print join(" \\\n\t",@sorted);
149             print "\n\n";
150     } else {
151             print "$module: ";
152             my @sorted = sort bydep keys %{$mod->{$module}};
153             print join(" ",@sorted);
154             print "\n";
155     }
156 }
157
158
159 sub build_ref_tables
160 {
161     my ($name, $sym_ar, $exp, $dep) = @_;
162
163         my $ksymtab = grep m/ __ksymtab/, @$sym_ar;
164
165     # gather the exported symbols
166         if($ksymtab){
167         # explicitly exported
168         foreach ( @$sym_ar ) {
169             / __ksymtab_(.*)$/ and do {
170                 warn "sym = $1\n" if $verbose;
171                 $exp->{$1} = $name;
172             };
173         }
174         } else {
175         # exporting all symbols
176         foreach ( @$sym_ar ) {
177             / [ABCDGRST] (.*)$/ and do {
178                 warn "syma = $1\n" if $verbose;
179                 $exp->{$1} = $name;
180             };
181         }
182         }
183
184     # this takes makes sure modules with no dependencies get listed
185     push @{$dep->{$name}}, 'printk' unless $name eq 'vmlinux';
186
187     # gather the unresolved symbols
188     foreach ( @$sym_ar ) {
189         !/ __this_module/ && / U (.*)$/ and do {
190             warn "und = $1\n" if $verbose;
191             push @{$dep->{$name}}, $1;
192         };
193     }
194 }
195
196 sub bydep
197 {
198     foreach my $f ( keys %{$mod->{$b}} ) {
199         if($f eq $a) {
200             return 1;
201         }
202     }
203     return -1;
204 }
205
206
207
208 __END__
209
210 =head1 NAME
211
212 depmod.pl - a cross platform script to generate kernel module
213 dependency lists (modules.conf) which can then be used by modprobe
214 on the target platform. 
215
216 It supports Linux 2.4 and 2.6 styles of modules.conf (auto-detected)
217
218 =head1 SYNOPSIS
219
220 depmod.pl [OPTION]... [basedir]...
221
222 Example:
223
224         depmod.pl -F linux/System.map -b target/lib/modules/2.6.11
225
226 =head1 DESCRIPTION
227
228 The purpose of this script is to automagically generate a list of of kernel
229 module dependencies.  This script produces dependency lists that should be
230 identical to the depmod program from the modutils package.  Unlike the depmod
231 binary, however, depmod.pl is designed to be run on your host system, not
232 on your target system.
233
234 This script was written by David Schleef <ds@schleef.org> to be used in
235 conjunction with the BusyBox modprobe applet.
236
237 =head1 OPTIONS
238
239 =over 4
240
241 =item B<-h --help>
242
243 This displays the help message.
244
245 =item B<-b --basedir>
246
247 The base directory uner which the target's modules will be found.  This
248 defaults to the /lib/modules directory. 
249
250 If you don't specify the kernel version, this script will search for
251 one under the specified based directory and use the first thing that
252 looks like a kernel version.
253
254 =item B<-k --kernel>
255
256 Kernel binary for the target (vmlinux).  You must either supply a kernel binary
257 or a kernel symbol file (using the -F option).
258
259 =item B<-F --kernelsyms>
260
261 Kernel symbol file for the target (System.map).
262
263 =item B<-n --stdout>
264
265 Write to stdout instead of modules.dep
266 kernel binary for the target (using the -k option).
267
268 =item B<--verbose>
269
270 Verbose (debug) output
271
272 =back
273
274 =head1 COPYRIGHT AND LICENSE
275
276  Copyright (c) 2001 David Schleef <ds@schleef.org>
277  Copyright (c) 2001 Erik Andersen <andersen@codepoet.org>
278  Copyright (c) 2001 Stuart Hughes <seh@zee2.com>
279  Copyright (c) 2002 Steven J. Hill <shill@broadcom.com>
280  Copyright (c) 2006 Freescale Semiconductor, Inc <stuarth@freescale.com>
281
282 This program is free software; you can redistribute it and/or modify it
283 under the same terms as Perl itself.
284
285 =head1 AUTHOR
286
287 David Schleef <ds@schleef.org>
288
289 =cut