scripts: modernize abi-check a bit

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2023-06-13 15:14:43 +02:00
parent 920c82fb9b
commit c0b70725e7

View File

@ -1,4 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl
use strict;
use warnings;
my $abinew = shift; my $abinew = shift;
my $abiold = shift; my $abiold = shift;
@ -22,30 +25,30 @@ my $count;
print "II: Checking ABI...\n"; print "II: Checking ABI...\n";
if ($skipabi) { if ($skipabi) {
print "WW: Explicitly asked to ignore ABI, running in no-fail mode\n"; print "WW: Explicitly asked to ignore ABI, running in no-fail mode\n";
$fail_exit = 0; $fail_exit = 0;
$abiskip = 1; $abiskip = 1;
$EE = "WW:"; $EE = "WW:";
} }
if ($prev_abistr ne $abistr) { if ($prev_abistr ne $abistr) {
print "II: Different ABI's, running in no-fail mode\n"; print "II: Different ABI's, running in no-fail mode\n";
$fail_exit = 0; $fail_exit = 0;
$EE = "WW:"; $EE = "WW:";
} }
if (not -f "$abinew" or not -f "$abiold") { if (not -f "$abinew" or not -f "$abiold") {
print "EE: Previous or current ABI file missing!\n"; print "EE: Previous or current ABI file missing!\n";
print " $abinew\n" if not -f "$abinew"; print " $abinew\n" if not -f "$abinew";
print " $abiold\n" if not -f "$abiold"; print " $abiold\n" if not -f "$abiold";
# Exit if the ABI files are missing, but return status based on whether # Exit if the ABI files are missing, but return status based on whether
# skip ABI was indicated. # skip ABI was indicated.
if ("$abiskip" eq "1") { if ("$abiskip" eq "1") {
exit(0); exit(0);
} else { } else {
exit(1); exit(1);
} }
} }
my %symbols; my %symbols;
@ -57,101 +60,97 @@ my %module_syms;
my $ignore = 0; my $ignore = 0;
print " Reading symbols/modules to ignore..."; print " Reading symbols/modules to ignore...";
for $file ("abi-blacklist") { for my $file ("abi-blacklist") {
if (-f $file) { next if !-f $file;
open(IGNORE, "< $file") or open(my $IGNORE_FH, '<', $file) or die "Could not open $file - $!";
die "Could not open $file";
while (<IGNORE>) { while (<$IGNORE_FH>) {
chomp; chomp;
if ($_ =~ m/M: (.*)/) { if ($_ =~ m/M: (.*)/) {
$modules_ignore{$1} = 1; $modules_ignore{$1} = 1;
} else { } else {
$symbols_ignore{$_} = 1; $symbols_ignore{$_} = 1;
}
$ignore++;
}
close(IGNORE);
} }
$ignore++;
}
close($IGNORE_FH);
} }
print "read $ignore symbols/modules.\n"; print "read $ignore symbols/modules.\n";
sub is_ignored($$) { sub is_ignored($$) {
my ($mod, $sym) = @_; my ($mod, $sym) = @_;
die "Missing module name in is_ignored()" if not defined($mod); die "Missing module name in is_ignored()" if not defined($mod);
die "Missing symbol name in is_ignored()" if not defined($sym); die "Missing symbol name in is_ignored()" if not defined($sym);
if (defined($symbols_ignore{$sym}) or defined($modules_ignore{$mod})) { if (defined($symbols_ignore{$sym}) or defined($modules_ignore{$mod})) {
return 1; return 1;
} }
return 0; return 0;
} }
# Read new syms first # Read new syms first
print " Reading new symbols ($abistr)..."; print " Reading new symbols ($abistr)...";
$count = 0; $count = 0;
open(NEW, "< $abinew") or open(my $NEW_FH, '<', $abinew) or die "Could not open $abinew - $!";
die "Could not open $abinew"; while (<$NEW_FH>) {
while (<NEW>) { chomp;
chomp; m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/;
m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; $symbols{$4}{'type'} = $1;
$symbols{$4}{'type'} = $1; $symbols{$4}{'loc'} = $2;
$symbols{$4}{'loc'} = $2; $symbols{$4}{'hash'} = $3;
$symbols{$4}{'hash'} = $3; $module_syms{$2} = 0;
$module_syms{$2} = 0; $count++;
$count++;
} }
close(NEW); close($NEW_FH);
print "read $count symbols.\n"; print "read $count symbols.\n";
# Now the old symbols, checking for missing ones # Now the old symbols, checking for missing ones
print " Reading old symbols..."; print " Reading old symbols...";
$count = 0; $count = 0;
open(OLD, "< $abiold") or open(my $OLD_FH, '<', $abiold) or die "Could not open $abiold - $!";
die "Could not open $abiold"; while (<$OLD_FH>) {
while (<OLD>) { chomp;
chomp; m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/;
m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; $symbols{$4}{'old_type'} = $1;
$symbols{$4}{'old_type'} = $1; $symbols{$4}{'old_loc'} = $2;
$symbols{$4}{'old_loc'} = $2; $symbols{$4}{'old_hash'} = $3;
$symbols{$4}{'old_hash'} = $3; $count++;
$count++;
} }
close(OLD); close($OLD_FH);
print "read $count symbols.\n"; print "read $count symbols.\n";
print "II: Checking for missing symbols in new ABI..."; print "II: Checking for missing symbols in new ABI...";
$count = 0; $count = 0;
foreach $sym (keys(%symbols)) { for my $sym (keys(%symbols)) {
if (!defined($symbols{$sym}{'type'})) { if (!defined($symbols{$sym}{'type'})) {
print "\n" if not $count; print "\n" if not $count;
printf(" MISS : %s%s\n", $sym, printf(" MISS : %s%s\n", $sym, is_ignored($symbols{$sym}{'old_loc'}, $sym) ? " (ignored)" : "");
is_ignored($symbols{$sym}{'old_loc'}, $sym) ? " (ignored)" : ""); $count++ if !is_ignored($symbols{$sym}{'old_loc'}, $sym);
$count++ if !is_ignored($symbols{$sym}{'old_loc'}, $sym); }
}
} }
print " " if $count; print " " if $count;
print "found $count missing symbols\n"; print "found $count missing symbols\n";
if ($count) { if ($count) {
print "$EE Symbols gone missing (what did you do!?!)\n"; print "$EE Symbols gone missing (what did you do!?!)\n";
$errors++; $errors++;
} }
print "II: Checking for new symbols in new ABI..."; print "II: Checking for new symbols in new ABI...";
$count = 0; $count = 0;
foreach $sym (keys(%symbols)) { for my $sym (keys(%symbols)) {
if (!defined($symbols{$sym}{'old_type'})) { if (!defined($symbols{$sym}{'old_type'})) {
print "\n" if not $count; print "\n" if not $count;
print " NEW : $sym\n"; print " NEW : $sym\n";
$count++; $count++;
} }
} }
print " " if $count; print " " if $count;
print "found $count new symbols\n"; print "found $count new symbols\n";
if ($count) { if ($count) {
print "WW: Found new symbols. Not recommended unless ABI was bumped\n"; print "WW: Found new symbols. Not recommended unless ABI was bumped\n";
} }
print "II: Checking for changes to ABI...\n"; print "II: Checking for changes to ABI...\n";
@ -159,37 +158,34 @@ $count = 0;
my $moved = 0; my $moved = 0;
my $changed_type = 0; my $changed_type = 0;
my $changed_hash = 0; my $changed_hash = 0;
foreach $sym (keys(%symbols)) { for my $sym (keys(%symbols)) {
if (!defined($symbols{$sym}{'old_type'}) or if (!defined($symbols{$sym}{'old_type'}) or !defined($symbols{$sym}{'type'})) {
!defined($symbols{$sym}{'type'})) { next;
next; }
}
# Changes in location don't hurt us, but log it anyway # Changes in location don't hurt us, but log it anyway
if ($symbols{$sym}{'loc'} ne $symbols{$sym}{'old_loc'}) { if ($symbols{$sym}{'loc'} ne $symbols{$sym}{'old_loc'}) {
printf(" MOVE : %-40s : %s => %s\n", $sym, $symbols{$sym}{'old_loc'}, printf(" MOVE : %-40s : %s => %s\n", $sym, $symbols{$sym}{'old_loc'}, $symbols{$sym}{'loc'});
$symbols{$sym}{'loc'}); $moved++;
$moved++; }
}
# Changes to export type are only bad if new type isn't # Changes to export type are only bad if new type isn't
# EXPORT_SYMBOL. Changing things to GPL are bad. # EXPORT_SYMBOL. Changing things to GPL are bad.
if ($symbols{$sym}{'type'} ne $symbols{$sym}{'old_type'}) { if ($symbols{$sym}{'type'} ne $symbols{$sym}{'old_type'}) {
printf(" TYPE : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_type'}. printf(" TYPE : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_type'}.
$symbols{$sym}{'type'}, is_ignored($symbols{$sym}{'loc'}, $sym) $symbols{$sym}{'type'}, is_ignored($symbols{$sym}{'loc'}, $sym)
? " (ignored)" : ""); ? " (ignored)" : "");
$changed_type++ if $symbols{$sym}{'type'} ne "EXPORT_SYMBOL" $changed_type++ if $symbols{$sym}{'type'} ne "EXPORT_SYMBOL" and !is_ignored($symbols{$sym}{'loc'}, $sym);
and !is_ignored($symbols{$sym}{'loc'}, $sym); }
}
# Changes to the hash are always bad # Changes to the hash are always bad
if ($symbols{$sym}{'hash'} ne $symbols{$sym}{'old_hash'}) { if ($symbols{$sym}{'hash'} ne $symbols{$sym}{'old_hash'}) {
printf(" HASH : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_hash'}, printf(" HASH : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_hash'},
$symbols{$sym}{'hash'}, is_ignored($symbols{$sym}{'loc'}, $sym) $symbols{$sym}{'hash'}, is_ignored($symbols{$sym}{'loc'}, $sym)
? " (ignored)" : ""); ? " (ignored)" : "");
$changed_hash++ if !is_ignored($symbols{$sym}{'loc'}, $sym); $changed_hash++ if !is_ignored($symbols{$sym}{'loc'}, $sym);
$module_syms{$symbols{$sym}{'loc'}}++; $module_syms{$symbols{$sym}{'loc'}}++;
} }
} }
print "WW: $moved symbols changed location\n" if $moved; print "WW: $moved symbols changed location\n" if $moved;
@ -198,17 +194,17 @@ print "$EE $changed_hash symbols changed hash and weren't ignored\n" if $changed
$errors++ if $changed_hash or $changed_type; $errors++ if $changed_hash or $changed_type;
if ($changed_hash) { if ($changed_hash) {
print "II: Module hash change summary...\n"; print "II: Module hash change summary...\n";
foreach $mod (sort { $module_syms{$b} <=> $module_syms{$a} } keys %module_syms) { for my $mod (sort { $module_syms{$b} <=> $module_syms{$a} } keys %module_syms) {
next if ! $module_syms{$mod}; next if ! $module_syms{$mod};
printf(" %-40s: %d\n", $mod, $module_syms{$mod}); printf(" %-40s: %d\n", $mod, $module_syms{$mod});
} }
} }
print "II: Done\n"; print "II: Done\n";
if ($errors) { if ($errors) {
exit($fail_exit); exit($fail_exit);
} else { } else {
exit(0); exit(0);
} }