| #!/usr/bin/perl -w |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # kabideps - a script tools to generate symbol referenced by other modules |
| # |
| # We use this script to check against reference Module.kabi files. |
| # |
| # Author: Xie XiuQi <xiexiuqi@huawei.com> |
| # Copyright (C) 2019 Huawei, Inc. |
| # |
| # This software may be freely redistributed under the terms of the GNU |
| # General Public License (GPL). |
| # |
| # usage: |
| # ./scripts/kabideps -m <module list> -s <symvers> -d <basedir of modules> -e |
| |
| use 5.010; |
| |
| use strict; |
| use Getopt::Long; |
| use File::Basename; |
| |
| my $MODULES; |
| my $SYMVERS; |
| my $EXCLUDE; |
| my $BASEDIR; |
| my $VERBOSE; |
| |
| my $PROG = basename $0; |
| |
| sub usage { |
| say "usage:"; |
| say " $PROG [--modules|m] [--symvers|s] [--basedir|d] [--exclude|e] [--verbose|v] [--help|h|?]"; |
| say " -m|--module"; |
| say " module list to be check (filename)"; |
| say " -d|--basedir"; |
| say " dir of ko"; |
| say " -s|--symvers"; |
| say " Module.symvers"; |
| say " -e|--exclude"; |
| say " exclude symbols which exported by the modules themselves"; |
| say " -v|--verbose:"; |
| say " show more info"; |
| say " -h|-?|--help:"; |
| say " show this usage"; |
| exit 0; |
| } |
| |
| usage() unless (@ARGV); |
| my $result = GetOptions( |
| 'module|m=s' => \$MODULES, |
| 'basedir|d=s' => \$BASEDIR, |
| 'symvers|s=s' => \$SYMVERS, |
| 'exclude|e!' => \$EXCLUDE, |
| 'verbose|v!' => \$VERBOSE, |
| 'help|h|?' => \&usage, |
| ) or usage(); |
| |
| my @mods; |
| |
| if ($MODULES) { |
| @mods = `cat $MODULES`; chomp @mods; |
| } |
| else { |
| @mods = `find $BASEDIR |grep -E ".ko\$"`; chomp @mods; |
| } |
| |
| my @allsyms = exclude_check(); |
| my $allmodsyms = {}; |
| |
| sub check_sym { |
| my $sym = shift; |
| my @res; |
| |
| foreach my $m (@mods) { |
| my @kmodsyms; |
| my $modname = basename $m; |
| |
| if ($m =~ /^\s*$/) { |
| next; |
| } |
| |
| if (!$allmodsyms->{$m}) { |
| @kmodsyms = `modprobe --dump-modversions $m |awk '{print \$2}'`; chomp @kmodsyms; |
| $allmodsyms->{$m} = \@kmodsyms; |
| } |
| |
| my $syms = $allmodsyms->{$m}; |
| for (@{$syms}) { |
| if ($sym eq $_) { |
| push @res, $modname; |
| } |
| } |
| } |
| |
| my $num = @res; |
| printf OUT "%d: ", $num; |
| for (@res) { |
| printf OUT "%s ", $_; |
| } |
| } |
| |
| sub exclude_check { |
| my @syms; |
| my @res; |
| my $i; |
| |
| if ($EXCLUDE) { |
| @syms = `cat $SYMVERS`; chomp @syms; |
| } |
| else { |
| @res = `cat $SYMVERS |awk '{print $2}'`; chomp @syms; |
| |
| return @res; |
| } |
| |
| my $total = @syms; |
| my $count; |
| say "excluding symbols exported by modules themselves..."; |
| for ($i = 0; $i < @syms; $i++) { |
| my @words = split(/\s+/, $syms[$i]); |
| my $found = 0; |
| |
| foreach my $mod (@mods) { |
| my $m; |
| |
| $words[2] = basename $words[2]; |
| $m = basename $mod; |
| $m =~ s/\.ko$//g; |
| |
| if ($words[2] eq $m) { |
| $found = 1; |
| last; |
| } |
| } |
| push @res, $words[1] unless($found); |
| |
| printf "\r%d/%d", $count++, $total; |
| } |
| print "\n"; |
| |
| return @res; |
| } |
| |
| my $output = "kabideps.txt"; |
| |
| open(OUT, ">", "$output") |
| || die "can't open >$output : $!"; |
| |
| my $total = @allsyms; |
| my $count; |
| say "checking symbols ..."; |
| for (@allsyms) { |
| printf OUT "%s: ", $_; |
| check_sym($_); |
| print OUT "\n"; |
| |
| printf "\r%d/%d", $count++, $total; |
| } |
| |
| close OUT; |