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