blob: 809dc08b39e85de8b384ccaeddc237262162ac27 [file] [log] [blame]
Eric Andersenc126f8f2001-07-30 19:32:03 +00001#!/usr/bin/perl -w
"Robert P. J. Day"63fc1a92006-07-02 19:47:05 +00002# vi: set sw=4 ts=4:
Eric Andersenc126f8f2001-07-30 19:32:03 +00003# Copyright (c) 2001 David Schleef <ds@schleef.org>
Eric Andersencb81e642003-07-14 21:21:08 +00004# Copyright (c) 2001 Erik Andersen <andersen@codepoet.org>
Rob Landleyd0498122006-03-21 16:35:50 +00005# Copyright (c) 2001 Stuart Hughes <seh@zee2.com>
"Steven J. Hill"adb058b2002-10-08 21:33:51 +00006# Copyright (c) 2002 Steven J. Hill <shill@broadcom.com>
Rob Landleyd0498122006-03-21 16:35:50 +00007# 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
Eric Andersenc7bda1c2004-03-15 08:29:22 +000014# This program is free software; you can redistribute it and/or modify it
Eric Andersenc126f8f2001-07-30 19:32:03 +000015# under the same terms as Perl itself.
Mike Frysinger2b6497b2009-05-05 20:14:12 -040016use Getopt::Long qw(:config no_auto_abbrev no_ignore_case);
Eric Andersenc126f8f2001-07-30 19:32:03 +000017use File::Find;
Rob Landleyd0498122006-03-21 16:35:50 +000018use strict;
Eric Andersenc126f8f2001-07-30 19:32:03 +000019
20# Set up some default values
Rob Landleyd0498122006-03-21 16:35:50 +000021my $kdir="";
Eric Andersenc126f8f2001-07-30 19:32:03 +000022my $basedir="";
Rob Landleyd0498122006-03-21 16:35:50 +000023my $kernel="";
24my $kernelsyms="";
Mike Frysingerd611ccc2007-07-13 04:37:12 +000025my $symprefix="";
Mike Frysinger2b6497b2009-05-05 20:14:12 -040026my $all=0;
27my $quick=0;
28my $errsyms=0;
"Steven J. Hill"adb058b2002-10-08 21:33:51 +000029my $stdout=0;
Eric Andersenc126f8f2001-07-30 19:32:03 +000030my $verbose=0;
Rob Landleyd0498122006-03-21 16:35:50 +000031my $help=0;
Rob Landley9a990aa2006-06-02 21:30:40 +000032my $nm = $ENV{'NM'} || "nm";
Eric Andersenc126f8f2001-07-30 19:32:03 +000033
Rob Landleyd0498122006-03-21 16:35:50 +000034# more globals
35my (@liblist) = ();
36my $exp = {};
37my $dep = {};
38my $mod = {};
39
40my $usage = <<TXT;
Denis Vlasenko9213a9e2006-09-17 16:28:10 +000041$0 -b basedir { -k <vmlinux> | -F <System.map> } [options]...
Rob Landleyd0498122006-03-21 16:35:50 +000042 Where:
Mike Frysingerd611ccc2007-07-13 04:37:12 +000043 -h --help : Show this help screen
44 -b --basedir : Modules base directory (e.g /lib/modules/<2.x.y>)
45 -k --kernel : Kernel binary for the target (e.g. vmlinux)
46 -F --kernelsyms : Kernel symbol file (e.g. System.map)
47 -n --stdout : Write to stdout instead of <basedir>/modules.dep
48 -v --verbose : Print out lots of debugging stuff
49 -P --symbol-prefix : Symbol prefix
Mike Frysinger2b6497b2009-05-05 20:14:12 -040050 -a --all : Probe all modules (default/only thing supported)
51 -e --errsyms : Report any symbols not supplied by modules/kernel
Rob Landleyd0498122006-03-21 16:35:50 +000052TXT
Eric Andersenc126f8f2001-07-30 19:32:03 +000053
54# get command-line options
Eric Andersenc126f8f2001-07-30 19:32:03 +000055GetOptions(
Mike Frysingerd611ccc2007-07-13 04:37:12 +000056 "help|h" => \$help,
57 "basedir|b=s" => \$basedir,
58 "kernel|k=s" => \$kernel,
59 "kernelsyms|F=s" => \$kernelsyms,
60 "stdout|n" => \$stdout,
61 "verbose|v" => \$verbose,
62 "symbol-prefix|P=s" => \$symprefix,
Mike Frysinger2b6497b2009-05-05 20:14:12 -040063 "all|a" => \$all,
64 # unsupported options
65 "quick|A" => \$quick,
66 # ignored options (for historical usage)
67 "quiet|q",
68 "root|r",
69 "unresolved-error|u"
Eric Andersenc126f8f2001-07-30 19:32:03 +000070);
71
Rob Landleyd0498122006-03-21 16:35:50 +000072die $usage if $help;
73die $usage unless $basedir && ( $kernel || $kernelsyms );
74die "can't use both -k and -F\n\n$usage" if $kernel && $kernelsyms;
Mike Frysinger2b6497b2009-05-05 20:14:12 -040075die "sorry, -A/--quick is not supported" if $quick;
76die "--errsyms requires --kernelsyms" if $errsyms && !$kernelsyms;
Eric Andersenc126f8f2001-07-30 19:32:03 +000077
Rob Landleyd0498122006-03-21 16:35:50 +000078# Strip any trailing or multiple slashes from basedir
Mike Frysinger2b6497b2009-05-05 20:14:12 -040079$basedir =~ s-/+$--g;
Rob Landleyd0498122006-03-21 16:35:50 +000080
81# The base directory should contain /lib/modules somewhere
Eric Andersenc126f8f2001-07-30 19:32:03 +000082if($basedir !~ m-/lib/modules-) {
83 warn "WARNING: base directory does not match ..../lib/modules\n";
84}
85
Rob Landleyd0498122006-03-21 16:35:50 +000086# if no kernel version is contained in the basedir, try to find one
87if($basedir !~ m-/lib/modules/\d\.\d-) {
88 opendir(BD, $basedir) or die "can't open basedir $basedir : $!\n";
89 foreach ( readdir(BD) ) {
90 next if /^\.\.?$/;
91 next unless -d "$basedir/$_";
92 warn "dir = $_\n" if $verbose;
93 if( /^\d\.\d/ ) {
94 $kdir = $_;
95 warn("Guessed module directory as $basedir/$kdir\n");
96 last;
97 }
98 }
99 closedir(BD);
100 die "Cannot find a kernel version under $basedir\n" unless $kdir;
101 $basedir = "$basedir/$kdir";
102}
103
104# Find the list of .o or .ko files living under $basedir
105warn "**** Locating all modules\n" if $verbose;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000106find sub {
Rob Landleyd0498122006-03-21 16:35:50 +0000107 my $file;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000108 if ( -f $_ && ! -d $_ ) {
Eric Andersenc126f8f2001-07-30 19:32:03 +0000109 $file = $File::Find::name;
Rob Landleyd0498122006-03-21 16:35:50 +0000110 if ( $file =~ /\.k?o$/ ) {
Eric Andersenc126f8f2001-07-30 19:32:03 +0000111 push(@liblist, $file);
Rob Landleyd0498122006-03-21 16:35:50 +0000112 warn "$file\n" if $verbose;
Eric Andersenc126f8f2001-07-30 19:32:03 +0000113 }
114 }
115}, $basedir;
Rob Landleyd0498122006-03-21 16:35:50 +0000116warn "**** Finished locating modules\n" if $verbose;
Eric Andersenc126f8f2001-07-30 19:32:03 +0000117
Rob Landleyd0498122006-03-21 16:35:50 +0000118foreach my $obj ( @liblist ){
Eric Andersenc126f8f2001-07-30 19:32:03 +0000119 # turn the input file name into a target tag name
Rob Landleyd0498122006-03-21 16:35:50 +0000120 my ($tgtname) = $obj =~ m-(/lib/modules/.*)$-;
Eric Andersenc126f8f2001-07-30 19:32:03 +0000121
Rob Landleyd0498122006-03-21 16:35:50 +0000122 warn "\nMODULE = $tgtname\n" if $verbose;
Eric Andersenc126f8f2001-07-30 19:32:03 +0000123
124 # get a list of symbols
Rob Landley9a990aa2006-06-02 21:30:40 +0000125 my @output=`$nm $obj`;
Eric Andersenc126f8f2001-07-30 19:32:03 +0000126
Rob Landleyd0498122006-03-21 16:35:50 +0000127 build_ref_tables($tgtname, \@output, $exp, $dep);
Eric Andersenc126f8f2001-07-30 19:32:03 +0000128}
129
130
Rob Landleyd0498122006-03-21 16:35:50 +0000131# vmlinux is a special name that is only used to resolve symbols
132my $tgtname = 'vmlinux';
Rob Landley9a990aa2006-06-02 21:30:40 +0000133my @output = $kernelsyms ? `cat $kernelsyms` : `$nm $kernel`;
Rob Landleyd0498122006-03-21 16:35:50 +0000134warn "\nMODULE = $tgtname\n" if $verbose;
135build_ref_tables($tgtname, \@output, $exp, $dep);
136
Mike Frysingerfa6c4842006-05-26 01:48:17 +0000137# resolve the dependencies for each module
138# reduce dependencies: remove unresolvable and resolved from vmlinux/System.map
Eric Andersenc126f8f2001-07-30 19:32:03 +0000139# remove duplicates
Rob Landleyd0498122006-03-21 16:35:50 +0000140foreach my $module (keys %$dep) {
141 warn "reducing module: $module\n" if $verbose;
Eric Andersenc126f8f2001-07-30 19:32:03 +0000142 $mod->{$module} = {};
143 foreach (@{$dep->{$module}}) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000144 if( $exp->{$_} ) {
Eric Andersenc126f8f2001-07-30 19:32:03 +0000145 warn "resolved symbol $_ in file $exp->{$_}\n" if $verbose;
146 next if $exp->{$_} =~ /vmlinux/;
147 $mod->{$module}{$exp->{$_}} = 1;
148 } else {
149 warn "unresolved symbol $_ in file $module\n";
150 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000151 }
Eric Andersenc126f8f2001-07-30 19:32:03 +0000152}
153
Mike Frysinger2b6497b2009-05-05 20:14:12 -0400154# build a complete dependency list for each module and make sure it
155# is kept in order proper order
156my $mod2 = {};
157sub maybe_unshift
158{
159 my ($array, $ele) = @_;
160 # chop off the leading path /lib/modules/<kver>/ as modprobe
161 # will handle relative paths just fine
162 $ele =~ s:^/lib/modules/[^/]*/::;
163 foreach (@{$array}) {
164 if ($_ eq $ele) {
165 return;
166 }
167 }
168 unshift (@{$array}, $ele);
169}
Mike Frysinger4c8a7212009-07-09 00:28:48 -0400170sub add_mod_deps
171{
172 my ($depth, $mod, $mod2, $module, $this_module) = @_;
173
174 $depth .= " ";
175 warn "${depth}loading deps of module: $this_module\n" if $verbose;
Mike Frysinger8ce1ad32010-11-16 07:15:00 -0500176 if (length($depth) > 50) {
177 die "too much recursion (circular dependencies in modules?)";
178 }
Mike Frysinger4c8a7212009-07-09 00:28:48 -0400179
180 foreach my $md (keys %{$mod->{$this_module}}) {
181 add_mod_deps ($depth, $mod, $mod2, $module, $md);
182 warn "${depth} outputting $md\n" if $verbose;
183 maybe_unshift (\@{$$mod2->{$module}}, $md);
184 }
185
186 if (!%{$mod->{$this_module}}) {
187 warn "${depth} no deps\n" if $verbose;
188 }
189}
Mike Frysinger2b6497b2009-05-05 20:14:12 -0400190foreach my $module (keys %$mod) {
Mike Frysinger4c8a7212009-07-09 00:28:48 -0400191 warn "filling out module: $module\n" if $verbose;
192 @{$mod2->{$module}} = ();
193 add_mod_deps ("", $mod, \$mod2, $module, $module);
Mike Frysinger2b6497b2009-05-05 20:14:12 -0400194}
195
Rob Landleyd0498122006-03-21 16:35:50 +0000196# figure out where the output should go
197if ($stdout == 0) {
Mike Frysinger4c8a7212009-07-09 00:28:48 -0400198 warn "writing $basedir/modules.dep\n" if $verbose;
Rob Landleyd0498122006-03-21 16:35:50 +0000199 open(STDOUT, ">$basedir/modules.dep")
200 or die "cannot open $basedir/modules.dep: $!";
201}
Sonic Zhang880eec82011-09-09 18:58:08 +0200202my $kseries = $basedir =~ m,/2\.4\.[^/]*, ? '2.4' : 'others';
Rob Landleyd0498122006-03-21 16:35:50 +0000203
204foreach my $module ( keys %$mod ) {
205 if($kseries eq '2.4') {
206 print "$module:\t";
207 my @sorted = sort bydep keys %{$mod->{$module}};
208 print join(" \\\n\t",@sorted);
209 print "\n\n";
210 } else {
Mike Frysinger2b6497b2009-05-05 20:14:12 -0400211 my $shortmod = $module;
212 $shortmod =~ s:^/lib/modules/[^/]*/::;
213 print "$shortmod:";
214 my @sorted = @{$mod2->{$module}};
215 printf " " if @sorted;
Rob Landleyd0498122006-03-21 16:35:50 +0000216 print join(" ",@sorted);
217 print "\n";
218 }
Eric Andersenc126f8f2001-07-30 19:32:03 +0000219}
220
"Steven J. Hill"adb058b2002-10-08 21:33:51 +0000221
Rob Landleyd0498122006-03-21 16:35:50 +0000222sub build_ref_tables
223{
224 my ($name, $sym_ar, $exp, $dep) = @_;
225
Mike Frysinger2b6497b2009-05-05 20:14:12 -0400226 my $ksymtab = grep m/ ${symprefix}__ksymtab/, @$sym_ar;
Rob Landleyd0498122006-03-21 16:35:50 +0000227
228 # gather the exported symbols
229 if($ksymtab){
230 # explicitly exported
231 foreach ( @$sym_ar ) {
Mike Frysinger2b6497b2009-05-05 20:14:12 -0400232 / ${symprefix}__ksymtab_(.*)$/ and do {
233 my $sym = ${symprefix} . $1;
234 warn "sym = $sym\n" if $verbose;
235 $exp->{$sym} = $name;
Rob Landleyd0498122006-03-21 16:35:50 +0000236 };
237 }
238 } else {
239 # exporting all symbols
240 foreach ( @$sym_ar ) {
Mike Frysingerdbd18f62007-11-18 06:13:58 +0000241 / [ABCDGRSTW] (.*)$/ and do {
Rob Landleyd0498122006-03-21 16:35:50 +0000242 warn "syma = $1\n" if $verbose;
243 $exp->{$1} = $name;
244 };
245 }
246 }
247
248 # this takes makes sure modules with no dependencies get listed
Mike Frysingerd611ccc2007-07-13 04:37:12 +0000249 push @{$dep->{$name}}, $symprefix . 'printk' unless $name eq 'vmlinux';
Rob Landleyd0498122006-03-21 16:35:50 +0000250
251 # gather the unresolved symbols
252 foreach ( @$sym_ar ) {
Mike Frysinger2b6497b2009-05-05 20:14:12 -0400253 !/ ${symprefix}__this_module/ && / U (.*)$/ and do {
Rob Landleyd0498122006-03-21 16:35:50 +0000254 warn "und = $1\n" if $verbose;
255 push @{$dep->{$name}}, $1;
256 };
257 }
258}
259
Eric Andersenc126f8f2001-07-30 19:32:03 +0000260sub bydep
261{
262 foreach my $f ( keys %{$mod->{$b}} ) {
263 if($f eq $a) {
264 return 1;
265 }
266 }
267 return -1;
268}
269
270
271
272__END__
273
274=head1 NAME
275
Rob Landleyd0498122006-03-21 16:35:50 +0000276depmod.pl - a cross platform script to generate kernel module
277dependency lists (modules.conf) which can then be used by modprobe
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000278on the target platform.
Rob Landleyd0498122006-03-21 16:35:50 +0000279
280It supports Linux 2.4 and 2.6 styles of modules.conf (auto-detected)
Eric Andersenc126f8f2001-07-30 19:32:03 +0000281
282=head1 SYNOPSIS
283
"Steven J. Hill"adb058b2002-10-08 21:33:51 +0000284depmod.pl [OPTION]... [basedir]...
Eric Andersenc126f8f2001-07-30 19:32:03 +0000285
286Example:
287
Rob Landleyd0498122006-03-21 16:35:50 +0000288 depmod.pl -F linux/System.map -b target/lib/modules/2.6.11
Eric Andersenc126f8f2001-07-30 19:32:03 +0000289
290=head1 DESCRIPTION
291
292The purpose of this script is to automagically generate a list of of kernel
Mike Frysingerfa6c4842006-05-26 01:48:17 +0000293module dependencies. This script produces dependency lists that should be
Eric Andersenc126f8f2001-07-30 19:32:03 +0000294identical to the depmod program from the modutils package. Unlike the depmod
295binary, however, depmod.pl is designed to be run on your host system, not
296on your target system.
297
298This script was written by David Schleef <ds@schleef.org> to be used in
299conjunction with the BusyBox modprobe applet.
300
301=head1 OPTIONS
302
303=over 4
304
305=item B<-h --help>
306
307This displays the help message.
308
309=item B<-b --basedir>
310
311The base directory uner which the target's modules will be found. This
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000312defaults to the /lib/modules directory.
Rob Landleyd0498122006-03-21 16:35:50 +0000313
314If you don't specify the kernel version, this script will search for
315one under the specified based directory and use the first thing that
316looks like a kernel version.
Eric Andersenc126f8f2001-07-30 19:32:03 +0000317
318=item B<-k --kernel>
319
Rob Landleyd0498122006-03-21 16:35:50 +0000320Kernel binary for the target (vmlinux). You must either supply a kernel binary
Eric Andersenc126f8f2001-07-30 19:32:03 +0000321or a kernel symbol file (using the -F option).
322
323=item B<-F --kernelsyms>
324
Rob Landleyd0498122006-03-21 16:35:50 +0000325Kernel symbol file for the target (System.map).
Eric Andersenc126f8f2001-07-30 19:32:03 +0000326
327=item B<-n --stdout>
328
Rob Landleyd0498122006-03-21 16:35:50 +0000329Write to stdout instead of modules.dep
Eric Andersenc126f8f2001-07-30 19:32:03 +0000330kernel binary for the target (using the -k option).
331
332=item B<--verbose>
333
Rob Landleyd0498122006-03-21 16:35:50 +0000334Verbose (debug) output
Eric Andersenc126f8f2001-07-30 19:32:03 +0000335
336=back
337
Rob Landleyd0498122006-03-21 16:35:50 +0000338=head1 COPYRIGHT AND LICENSE
Eric Andersenc126f8f2001-07-30 19:32:03 +0000339
Rob Landleyd0498122006-03-21 16:35:50 +0000340 Copyright (c) 2001 David Schleef <ds@schleef.org>
341 Copyright (c) 2001 Erik Andersen <andersen@codepoet.org>
342 Copyright (c) 2001 Stuart Hughes <seh@zee2.com>
343 Copyright (c) 2002 Steven J. Hill <shill@broadcom.com>
344 Copyright (c) 2006 Freescale Semiconductor, Inc <stuarth@freescale.com>
345
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000346This program is free software; you can redistribute it and/or modify it
Eric Andersenc126f8f2001-07-30 19:32:03 +0000347under the same terms as Perl itself.
348
349=head1 AUTHOR
350
351David Schleef <ds@schleef.org>
352
353=cut