1c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai#!/usr/bin/perl -w 2c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 3c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# (C) Copyright IBM Corporation 2006. 4c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# Released under GPL v2. 5c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# Author : Ram Pai (linuxram@us.ibm.com) 6c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 7c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c 8c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 9c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 10c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiuse Getopt::Std; 11c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiuse strict; 12c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 13c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paisub numerically { 14c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my $no1 = (split /\s+/, $a)[1]; 15c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my $no2 = (split /\s+/, $b)[1]; 16c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai return $no1 <=> $no2; 17c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 18c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 19c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paisub alphabetically { 20c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my ($module1, $value1) = @{$a}; 21c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my ($module2, $value2) = @{$b}; 22c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai return $value1 <=> $value2 || $module2 cmp $module1; 23c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 24c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 25c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paisub print_depends_on { 26c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my ($href) = @_; 27c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print "\n"; 28bdabc7a345db97b3839c2c3deef40023cf8017efJim Cromie for my $mod (sort keys %$href) { 29bdabc7a345db97b3839c2c3deef40023cf8017efJim Cromie my $list = $href->{$mod}; 30c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print "\t$mod:\n"; 31c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai foreach my $sym (sort numerically @{$list}) { 32c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my ($symbol, $no) = split /\s+/, $sym; 33bdabc7a345db97b3839c2c3deef40023cf8017efJim Cromie printf("\t\t%-25s\n", $symbol); 34c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 35c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print "\n"; 36c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 37c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print "\n"; 38c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print "~"x80 , "\n"; 39c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 40c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 41c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paisub usage { 42c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print "Usage: @_ -h -k Module.symvers [ -o outputfile ] \n", 43c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "\t-f: treat all the non-option argument as .mod.c files. ", 44c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "Recommend using this as the last option\n", 45c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "\t-h: print detailed help\n", 46c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "\t-k: the path to Module.symvers file. By default uses ", 47c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "the file from the current directory\n", 48c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "\t-o outputfile: output the report to outputfile\n"; 49c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai exit 0; 50c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 51c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 52c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paisub collectcfiles { 53de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie my @file; 54de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie while (<.tmp_versions/*.mod>) { 55de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie open my $fh, '<', $_ or die "cannot open $_: $!\n"; 56de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie push (@file, 57de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie grep s/\.ko/.mod.c/, # change the suffix 58de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie grep m/.+\.ko/, # find the .ko path 59de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie <$fh>); # lines in opened file 60de7b0b4110795be914e6cafdfec4276b2618cc78Jim Cromie } 6191416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger chomp @file; 6291416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger return @file; 63c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 64c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 65c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paimy (%SYMBOL, %MODULE, %opt, @allcfiles); 66c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 67c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiif (not getopts('hk:o:f',\%opt) or defined $opt{'h'}) { 68c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai usage($0); 69c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 70c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 71c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiif (defined $opt{'f'}) { 72c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai @allcfiles = @ARGV; 73c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} else { 74c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai @allcfiles = collectcfiles(); 75c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 76c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 77c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiif (not defined $opt{'k'}) { 78c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai $opt{'k'} = "Module.symvers"; 79c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 80c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 8191416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemmingeropen (my $module_symvers, '<', $opt{'k'}) 8291416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger or die "Sorry, cannot open $opt{'k'}: $!\n"; 83c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 84c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiif (defined $opt{'o'}) { 8591416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger open (my $out, '>', $opt{'o'}) 8691416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger or die "Sorry, cannot open $opt{'o'} $!\n"; 8791416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger 8891416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger select $out; 89c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 9091416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger 91c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 92c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# collect all the symbols and their attributes from the 93c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# Module.symvers file 94c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 9591416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemmingerwhile ( <$module_symvers> ) { 96c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai chomp; 97c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my (undef, $symbol, $module, $gpl) = split; 98c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai $SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl]; 99c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 10091416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemmingerclose($module_symvers); 101c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 102c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 103c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# collect the usage count of each symbol. 104c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 105ca995cbf77f3df599b7e751c2d08d90787c65c45Jim Cromiemy $modversion_warnings = 0; 106ca995cbf77f3df599b7e751c2d08d90787c65c45Jim Cromie 107c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiforeach my $thismod (@allcfiles) { 10891416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger my $module; 10991416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger 11091416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger unless (open ($module, '<', $thismod)) { 11191416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger warn "Sorry, cannot open $thismod: $!\n"; 112c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai next; 113c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 11491416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger 115c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my $state=0; 11691416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger while ( <$module> ) { 117c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai chomp; 11888f567f3a3c1901a40150b43fda87adad1b3e807Ram Pai if ($state == 0) { 119c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai $state = 1 if ($_ =~ /static const struct modversion_info/); 120c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai next; 121c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 12288f567f3a3c1901a40150b43fda87adad1b3e807Ram Pai if ($state == 1) { 123c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai $state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/); 124c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai next; 125c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 12688f567f3a3c1901a40150b43fda87adad1b3e807Ram Pai if ($state == 2) { 127cf9a6adeae706849990e5bdd4f32cb45d667e0c5Adrian Bunk if ( $_ !~ /0x[0-9a-f]+,/ ) { 128c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai next; 129c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 130c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my $sym = (split /([,"])/,)[4]; 131c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}}; 132c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai $SYMBOL{ $sym } = [ $module, $value+1, $symbol, $gpl]; 133c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai push(@{$MODULE{$thismod}} , $sym); 134c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 135c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 13688f567f3a3c1901a40150b43fda87adad1b3e807Ram Pai if ($state != 2) { 137ca995cbf77f3df599b7e751c2d08d90787c65c45Jim Cromie warn "WARNING:$thismod is not built with CONFIG_MODVERSIONS enabled\n"; 138ca995cbf77f3df599b7e751c2d08d90787c65c45Jim Cromie $modversion_warnings++; 139c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 14091416cfdf98bdbc828fd3e5ca7208beba5979d63Stephen Hemminger close($module); 141c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 142c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 143c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprint "\tThis file reports the exported symbols usage patterns by in-tree\n", 144c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "\t\t\t\tmodules\n"; 145c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("%s\n\n\n","x"x80); 146c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("\t\t\t\tINDEX\n\n\n"); 147c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("SECTION 1: Usage counts of all exported symbols\n"); 148c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("SECTION 2: List of modules and the exported symbols they use\n"); 149c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("%s\n\n\n","x"x80); 150c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("SECTION 1:\tThe exported symbols and their usage count\n\n"); 151c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("%-25s\t%-25s\t%-5s\t%-25s\n", "Symbol", "Module", "Usage count", 152c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai "export type"); 153c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 154c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 155c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# print the list of unused exported symbols 156c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai# 157c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiforeach my $list (sort alphabetically values(%SYMBOL)) { 158c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my ($module, $value, $symbol, $gpl) = @{$list}; 159c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai printf("%-25s\t%-25s\t%-10s\t", $symbol, $module, $value); 160c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai if (defined $gpl) { 161c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai printf("%-25s\n",$gpl); 162c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } else { 163c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai printf("\n"); 164c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 165c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 166c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("%s\n\n\n","x"x80); 167c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 168c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprintf("SECTION 2:\n\tThis section reports export-symbol-usage of in-kernel 169c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paimodules. Each module lists the modules, and the symbols from that module that 170c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiit uses. Each listed symbol reports the number of modules using it\n"); 171c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai 172ca995cbf77f3df599b7e751c2d08d90787c65c45Jim Cromieprint "\nNOTE: Got $modversion_warnings CONFIG_MODVERSIONS warnings\n\n" 173ca995cbf77f3df599b7e751c2d08d90787c65c45Jim Cromie if $modversion_warnings; 174ca995cbf77f3df599b7e751c2d08d90787c65c45Jim Cromie 175c5e3003381f4e39773a1758a9eb68dff9740a56cRam Paiprint "~"x80 , "\n"; 176bdabc7a345db97b3839c2c3deef40023cf8017efJim Cromiefor my $thismod (sort keys %MODULE) { 177bdabc7a345db97b3839c2c3deef40023cf8017efJim Cromie my $list = $MODULE{$thismod}; 178c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my %depends; 179c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai $thismod =~ s/\.mod\.c/.ko/; 180c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print "\t\t\t$thismod\n"; 181c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai foreach my $symbol (@{$list}) { 182c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai my ($module, $value, undef, $gpl) = @{$SYMBOL{$symbol}}; 183c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai push (@{$depends{"$module"}}, "$symbol $value"); 184c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai } 185c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai print_depends_on(\%depends); 186c5e3003381f4e39773a1758a9eb68dff9740a56cRam Pai} 187