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