# vi: set ts=4:
# Copyright (c) 2001 David Schleef <ds@schleef.org>
# Copyright (c) 2001 Erik Andersen <andersen@codepoet.org>
-# Copyright (c) 2001 Stuart Hughes <stuarth@lineo.com>
+# Copyright (c) 2001 Stuart Hughes <seh@zee2.com>
# Copyright (c) 2002 Steven J. Hill <shill@broadcom.com>
+# Copyright (c) 2006 Freescale Semiconductor, Inc <stuarth@freescale.com>
+#
+# History:
+# March 2006: Stuart Hughes <stuarth@freescale.com>.
+# Significant updates, including implementing the '-F' option
+# and adding support for 2.6 kernels.
+
# This program is free software; you can redistribute it and/or modify it
# under the same terms as Perl itself.
-
-# TODO -- use strict mode...
-#use strict;
-
use Getopt::Long;
use File::Find;
-
+use strict;
# Set up some default values
-
+my $kdir="";
my $basedir="";
-my $kernel;
-my $kernelsyms;
+my $kernel="";
+my $kernelsyms="";
my $stdout=0;
my $verbose=0;
-
+my $help=0;
+
+# more globals
+my (@liblist) = ();
+my $exp = {};
+my $dep = {};
+my $mod = {};
+
+my $usage = <<TXT;
+$0 -b basedir { -k <vmlinux> | -F <System.map> } [options]...
+ Where:
+ -h --help : Show this help screen
+ -b --basedir : Modules base directory (e.g /lib/modules/<2.x.y>)
+ -k --kernel : Kernel binary for the target (e.g. vmlinux)
+ -F --kernelsyms : Kernel symbol file (e.g. System.map)
+ -n --stdout : Write to stdout instead of <basedir>/modules.dep
+ -v --verbose : Print out lots of debugging stuff
+TXT
# get command-line options
-
-my %opt;
-
GetOptions(
- \%opt,
- "help|h",
- "basedir|b=s" => \$basedir,
- "kernel|k=s" => \$kernel,
+ "help|h" => \$help,
+ "basedir|b=s" => \$basedir,
+ "kernel|k=s" => \$kernel,
"kernelsyms|F=s" => \$kernelsyms,
- "stdout|n" => \$stdout,
- "verbose|v" => \$verbose,
+ "stdout|n" => \$stdout,
+ "verbose|v" => \$verbose,
);
-if (defined $opt{help}) {
- print
- " $0 [OPTION]... [basedir]\n",
- " -h --help\t\tShow this help screen\n",
- " -b --basedir\tModules base directory (defaults to /lib/modules)\n",
- " -k --kernel\tKernel binary for the target\n",
- " -F --kernelsyms\tKernel symbol file\n",
- " -n --stdout\tWrite to stdout instead of <basedir>/modules.dep\n",
- " -v --verbose\tPrint out lots of debugging stuff\n",
- ;
- exit 1;
-}
+die $usage if $help;
+die $usage unless $basedir && ( $kernel || $kernelsyms );
+die "can't use both -k and -F\n\n$usage" if $kernel && $kernelsyms;
+# Strip any trailing or multiple slashes from basedir
+$basedir =~ s-(/)\1+-/-g;
+
+# The base directory should contain /lib/modules somewhere
if($basedir !~ m-/lib/modules-) {
warn "WARNING: base directory does not match ..../lib/modules\n";
}
-# Find the list of .o files living under $basedir
-#if ($verbose) { printf "Locating all modules\n"; }
-my($ofile) = "";
-my($file) = "";
-my(@liblist) = ();
+# if no kernel version is contained in the basedir, try to find one
+if($basedir !~ m-/lib/modules/\d\.\d-) {
+ opendir(BD, $basedir) or die "can't open basedir $basedir : $!\n";
+ foreach ( readdir(BD) ) {
+ next if /^\.\.?$/;
+ next unless -d "$basedir/$_";
+ warn "dir = $_\n" if $verbose;
+ if( /^\d\.\d/ ) {
+ $kdir = $_;
+ warn("Guessed module directory as $basedir/$kdir\n");
+ last;
+ }
+ }
+ closedir(BD);
+ die "Cannot find a kernel version under $basedir\n" unless $kdir;
+ $basedir = "$basedir/$kdir";
+}
+
+# Find the list of .o or .ko files living under $basedir
+warn "**** Locating all modules\n" if $verbose;
find sub {
+ my $file;
if ( -f $_ && ! -d $_ ) {
$file = $File::Find::name;
- if ( $file =~ /.o$/ ) {
+ if ( $file =~ /\.k?o$/ ) {
push(@liblist, $file);
- if ($verbose) { printf "$file\n"; }
+ warn "$file\n" if $verbose;
}
}
}, $basedir;
-if ($verbose) { printf "Finished locating modules\n"; }
+warn "**** Finished locating modules\n" if $verbose;
-foreach $obj ( @liblist, $kernel ){
+foreach my $obj ( @liblist ){
# turn the input file name into a target tag name
- # vmlinux is a special that is only used to resolve symbols
- if($obj =~ /vmlinux/) {
- $tgtname = "vmlinux";
+ my ($tgtname) = $obj =~ m-(/lib/modules/.*)$-;
+
+ warn "\nMODULE = $tgtname\n" if $verbose;
+
+ # get a list of symbols
+ my @output=`nm $obj`;
+
+ build_ref_tables($tgtname, \@output, $exp, $dep);
+}
+
+
+# vmlinux is a special name that is only used to resolve symbols
+my $tgtname = 'vmlinux';
+my @output = $kernelsyms ? `cat $kernelsyms` : `nm $kernel`;
+warn "\nMODULE = $tgtname\n" if $verbose;
+build_ref_tables($tgtname, \@output, $exp, $dep);
+
+# resolve the dependancies for each module
+# reduce dependancies: remove unresolvable and resolved from vmlinux/System.map
+# remove duplicates
+foreach my $module (keys %$dep) {
+ warn "reducing module: $module\n" if $verbose;
+ $mod->{$module} = {};
+ foreach (@{$dep->{$module}}) {
+ if( $exp->{$_} ) {
+ warn "resolved symbol $_ in file $exp->{$_}\n" if $verbose;
+ next if $exp->{$_} =~ /vmlinux/;
+ $mod->{$module}{$exp->{$_}} = 1;
+ } else {
+ warn "unresolved symbol $_ in file $module\n";
+ }
+ }
+}
+
+# figure out where the output should go
+if ($stdout == 0) {
+ open(STDOUT, ">$basedir/modules.dep")
+ or die "cannot open $basedir/modules.dep: $!";
+}
+my $kseries = $basedir =~ m,/2\.6\.[^/]*, ? '2.6' : '2.4';
+
+foreach my $module ( keys %$mod ) {
+ if($kseries eq '2.4') {
+ print "$module:\t";
+ my @sorted = sort bydep keys %{$mod->{$module}};
+ print join(" \\\n\t",@sorted);
+ print "\n\n";
} else {
- ($tgtname) = $obj =~ m-(/lib/modules/.*)$-;
+ print "$module: ";
+ my @sorted = sort bydep keys %{$mod->{$module}};
+ print join(" ",@sorted);
+ print "\n";
}
+}
- warn "MODULE = $tgtname\n" if $verbose;
- # get a list of symbols
- @output=`nm $obj`;
- $ksymtab=grep m/ __ksymtab/, @output;
+sub build_ref_tables
+{
+ my ($name, $sym_ar, $exp, $dep) = @_;
+
+ my $ksymtab = grep m/ __ksymtab/, @$sym_ar;
# gather the exported symbols
if($ksymtab){
# explicitly exported
- foreach ( @output ) {
+ foreach ( @$sym_ar ) {
/ __ksymtab_(.*)$/ and do {
warn "sym = $1\n" if $verbose;
- $exp->{$1} = $tgtname;
+ $exp->{$1} = $name;
};
}
} else {
# exporting all symbols
- foreach ( @output) {
+ foreach ( @$sym_ar ) {
/ [ABCDGRST] (.*)$/ and do {
warn "syma = $1\n" if $verbose;
- $exp->{$1} = $tgtname;
+ $exp->{$1} = $name;
};
}
}
+
+ # this takes makes sure modules with no dependencies get listed
+ push @{$dep->{$name}}, 'printk' unless $name eq 'vmlinux';
+
# gather the unresolved symbols
- foreach ( @output ) {
+ foreach ( @$sym_ar ) {
!/ __this_module/ && / U (.*)$/ and do {
warn "und = $1\n" if $verbose;
- push @{$dep->{$tgtname}}, $1;
+ push @{$dep->{$name}}, $1;
};
}
}
-
-# reduce dependancies: remove unresolvable and resolved from vmlinux
-# remove duplicates
-foreach $module (keys %$dep) {
- $mod->{$module} = {};
- foreach (@{$dep->{$module}}) {
- if( $exp->{$_} ) {
- warn "resolved symbol $_ in file $exp->{$_}\n" if $verbose;
- next if $exp->{$_} =~ /vmlinux/;
- $mod->{$module}{$exp->{$_}} = 1;
- } else {
- warn "unresolved symbol $_ in file $module\n";
- }
- }
-}
-
-# resolve the dependancies for each module
-if ($stdout == 1) {
- foreach $module ( keys %$mod ) {
- print "$module:\t";
- @sorted = sort bydep keys %{$mod->{$module}};
- print join(" \\\n\t",@sorted);
- print "\n\n";
- }
-} else {
- open(OFILE, ">$basedir/modules.dep");
- foreach $module ( keys %$mod ) {
- print OFILE "$module:\t";
- @sorted = sort bydep keys %{$mod->{$module}};
- print OFILE join(" \\\n\t",@sorted);
- print OFILE "\n\n";
- }
-}
-
-
sub bydep
{
foreach my $f ( keys %{$mod->{$b}} ) {
=head1 NAME
-depmod.pl - a cross platform script to generate kernel module dependency
- lists which can then be used by modprobe.
+depmod.pl - a cross platform script to generate kernel module
+dependency lists (modules.conf) which can then be used by modprobe
+on the target platform.
+
+It supports Linux 2.4 and 2.6 styles of modules.conf (auto-detected)
=head1 SYNOPSIS
Example:
- depmod.pl -F linux/System.map target/lib/modules
+ depmod.pl -F linux/System.map -b target/lib/modules/2.6.11
=head1 DESCRIPTION
=item B<-b --basedir>
The base directory uner which the target's modules will be found. This
-defaults to the /lib/modules directory.
+defaults to the /lib/modules directory.
+
+If you don't specify the kernel version, this script will search for
+one under the specified based directory and use the first thing that
+looks like a kernel version.
=item B<-k --kernel>
-Kernel binary for the target. You must either supply a kernel binary
+Kernel binary for the target (vmlinux). You must either supply a kernel binary
or a kernel symbol file (using the -F option).
=item B<-F --kernelsyms>
-Kernel symbol file for the target. You must supply either a kernel symbol file
-kernel binary for the target (using the -k option).
+Kernel symbol file for the target (System.map).
=item B<-n --stdout>
-Write to stdout instead of modules.dep. This is currently hard coded...
+Write to stdout instead of modules.dep
kernel binary for the target (using the -k option).
=item B<--verbose>
-Be verbose (not implemented)
+Verbose (debug) output
=back
-=head1 COPYRIGHT
+=head1 COPYRIGHT AND LICENSE
+
+ Copyright (c) 2001 David Schleef <ds@schleef.org>
+ Copyright (c) 2001 Erik Andersen <andersen@codepoet.org>
+ Copyright (c) 2001 Stuart Hughes <seh@zee2.com>
+ Copyright (c) 2002 Steven J. Hill <shill@broadcom.com>
+ Copyright (c) 2006 Freescale Semiconductor, Inc <stuarth@freescale.com>
-Copyright (c) 2001 David Schleef <ds@schleef.org>
-Copyright (c) 2001 Erik Andersen <andersen@codepoet.org>
-Copyright (c) 2001 Stuart Hughes <stuarth@lineo.com>
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.