Blame view
scripts/export_report.pl
4.53 KB
c5e300338
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#!/usr/bin/perl -w # # (C) Copyright IBM Corporation 2006. # Released under GPL v2. # Author : Ram Pai (linuxram@us.ibm.com) # # Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c # use Getopt::Std; use strict; sub numerically { my $no1 = (split /\s+/, $a)[1]; my $no2 = (split /\s+/, $b)[1]; return $no1 <=> $no2; } sub alphabetically { my ($module1, $value1) = @{$a}; my ($module2, $value2) = @{$b}; return $value1 <=> $value2 || $module2 cmp $module1; } sub print_depends_on { my ($href) = @_; print " "; |
bdabc7a34
|
29 30 |
for my $mod (sort keys %$href) { my $list = $href->{$mod}; |
c5e300338
|
31 32 33 34 |
print "\t$mod: "; foreach my $sym (sort numerically @{$list}) { my ($symbol, $no) = split /\s+/, $sym; |
bdabc7a34
|
35 36 |
printf("\t\t%-25s ", $symbol); |
c5e300338
|
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
} print " "; } print " "; print "~"x80 , " "; } sub usage { print "Usage: @_ -h -k Module.symvers [ -o outputfile ] ", "\t-f: treat all the non-option argument as .mod.c files. ", "Recommend using this as the last option ", "\t-h: print detailed help ", "\t-k: the path to Module.symvers file. By default uses ", "the file from the current directory ", "\t-o outputfile: output the report to outputfile "; exit 0; } sub collectcfiles { |
de7b0b411
|
64 65 66 67 68 69 70 71 72 |
my @file; while (<.tmp_versions/*.mod>) { open my $fh, '<', $_ or die "cannot open $_: $! "; push (@file, grep s/\.ko/.mod.c/, # change the suffix grep m/.+\.ko/, # find the .ko path <$fh>); # lines in opened file } |
91416cfdf
|
73 74 |
chomp @file; return @file; |
c5e300338
|
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
} my (%SYMBOL, %MODULE, %opt, @allcfiles); if (not getopts('hk:o:f',\%opt) or defined $opt{'h'}) { usage($0); } if (defined $opt{'f'}) { @allcfiles = @ARGV; } else { @allcfiles = collectcfiles(); } if (not defined $opt{'k'}) { $opt{'k'} = "Module.symvers"; } |
91416cfdf
|
92 93 94 |
open (my $module_symvers, '<', $opt{'k'}) or die "Sorry, cannot open $opt{'k'}: $! "; |
c5e300338
|
95 96 |
if (defined $opt{'o'}) { |
91416cfdf
|
97 98 99 100 101 |
open (my $out, '>', $opt{'o'}) or die "Sorry, cannot open $opt{'o'} $! "; select $out; |
c5e300338
|
102 |
} |
91416cfdf
|
103 |
|
c5e300338
|
104 105 106 107 |
# # collect all the symbols and their attributes from the # Module.symvers file # |
91416cfdf
|
108 |
while ( <$module_symvers> ) { |
c5e300338
|
109 110 111 112 |
chomp; my (undef, $symbol, $module, $gpl) = split; $SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl]; } |
91416cfdf
|
113 |
close($module_symvers); |
c5e300338
|
114 115 116 117 |
# # collect the usage count of each symbol. # |
ca995cbf7
|
118 |
my $modversion_warnings = 0; |
c5e300338
|
119 |
foreach my $thismod (@allcfiles) { |
91416cfdf
|
120 121 122 123 124 |
my $module; unless (open ($module, '<', $thismod)) { warn "Sorry, cannot open $thismod: $! "; |
c5e300338
|
125 126 |
next; } |
91416cfdf
|
127 |
|
c5e300338
|
128 |
my $state=0; |
91416cfdf
|
129 |
while ( <$module> ) { |
c5e300338
|
130 |
chomp; |
88f567f3a
|
131 |
if ($state == 0) { |
c5e300338
|
132 133 134 |
$state = 1 if ($_ =~ /static const struct modversion_info/); next; } |
88f567f3a
|
135 |
if ($state == 1) { |
c5e300338
|
136 137 138 |
$state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/); next; } |
88f567f3a
|
139 |
if ($state == 2) { |
cf9a6adea
|
140 |
if ( $_ !~ /0x[0-9a-f]+,/ ) { |
c5e300338
|
141 142 143 144 145 146 147 148 |
next; } my $sym = (split /([,"])/,)[4]; my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}}; $SYMBOL{ $sym } = [ $module, $value+1, $symbol, $gpl]; push(@{$MODULE{$thismod}} , $sym); } } |
88f567f3a
|
149 |
if ($state != 2) { |
ca995cbf7
|
150 151 152 |
warn "WARNING:$thismod is not built with CONFIG_MODVERSIONS enabled "; $modversion_warnings++; |
c5e300338
|
153 |
} |
91416cfdf
|
154 |
close($module); |
c5e300338
|
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
} print "\tThis file reports the exported symbols usage patterns by in-tree ", "\t\t\t\tmodules "; printf("%s ","x"x80); printf("\t\t\t\tINDEX "); printf("SECTION 1: Usage counts of all exported symbols "); printf("SECTION 2: List of modules and the exported symbols they use "); printf("%s ","x"x80); printf("SECTION 1:\tThe exported symbols and their usage count "); printf("%-25s\t%-25s\t%-5s\t%-25s ", "Symbol", "Module", "Usage count", "export type"); # # print the list of unused exported symbols # foreach my $list (sort alphabetically values(%SYMBOL)) { my ($module, $value, $symbol, $gpl) = @{$list}; printf("%-25s\t%-25s\t%-10s\t", $symbol, $module, $value); if (defined $gpl) { printf("%-25s ",$gpl); } else { printf(" "); } } printf("%s ","x"x80); printf("SECTION 2: \tThis section reports export-symbol-usage of in-kernel modules. Each module lists the modules, and the symbols from that module that it uses. Each listed symbol reports the number of modules using it "); |
ca995cbf7
|
208 209 210 211 212 |
print " NOTE: Got $modversion_warnings CONFIG_MODVERSIONS warnings " if $modversion_warnings; |
c5e300338
|
213 214 |
print "~"x80 , " "; |
bdabc7a34
|
215 216 |
for my $thismod (sort keys %MODULE) { my $list = $MODULE{$thismod}; |
c5e300338
|
217 218 219 220 221 222 223 224 225 226 |
my %depends; $thismod =~ s/\.mod\.c/.ko/; print "\t\t\t$thismod "; foreach my $symbol (@{$list}) { my ($module, $value, undef, $gpl) = @{$SYMBOL{$symbol}}; push (@{$depends{"$module"}}, "$symbol $value"); } print_depends_on(\%depends); } |