#!/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 # 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 -s -d -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;