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