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