diff options
-rwxr-xr-x | examples/depmod.pl | 258 |
1 files changed, 156 insertions, 102 deletions
diff --git a/examples/depmod.pl b/examples/depmod.pl index 9af1922..3211c8a 100755 --- a/examples/depmod.pl +++ b/examples/depmod.pl @@ -2,151 +2,196 @@ # 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}} ) { @@ -163,8 +208,11 @@ __END__ =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 @@ -172,7 +220,7 @@ depmod.pl [OPTION]... [basedir]... 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 @@ -196,34 +244,40 @@ This displays the help message. =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. |