| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | #!/usr/bin/perl -w | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | my $abinew = shift; | 
					
						
							|  |  |  | my $abiold = shift; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | my $skipabi = shift; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-21 13:27:31 +03:00
										 |  |  | # to catch multiple abi-prev-* files being passed in | 
					
						
							|  |  |  | die "invalid value for skipabi parameter\n" | 
					
						
							|  |  |  | 	if (defined($skipabi) && $skipabi !~ /^[01]$/); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | $abinew =~ /abi-(.*)/; | 
					
						
							| 
									
										
										
										
											2018-03-21 13:27:31 +03:00
										 |  |  | my $abistr = $1; | 
					
						
							|  |  |  | $abiold =~ /abi-prev-(.*)/; | 
					
						
							|  |  |  | my $prev_abistr = $1; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | my $fail_exit = 1; | 
					
						
							|  |  |  | my $EE = "EE:"; | 
					
						
							|  |  |  | my $errors = 0; | 
					
						
							|  |  |  | my $abiskip = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | my $count; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | print "II: Checking ABI...\n"; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | if ($skipabi) { | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | 	print "WW: Explicitly asked to ignore ABI, running in no-fail mode\n"; | 
					
						
							|  |  |  | 	$fail_exit = 0; | 
					
						
							|  |  |  | 	$abiskip = 1; | 
					
						
							|  |  |  | 	$EE = "WW:"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-21 13:27:31 +03:00
										 |  |  | if ($prev_abistr ne $abistr) { | 
					
						
							|  |  |  | 	print "II: Different ABI's, running in no-fail mode\n"; | 
					
						
							|  |  |  | 	$fail_exit = 0; | 
					
						
							|  |  |  | 	$EE = "WW:"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | if (not -f "$abinew" or not -f "$abiold") { | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | 	print "EE: Previous or current ABI file missing!\n"; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | 	print "    $abinew\n" if not -f "$abinew"; | 
					
						
							|  |  |  | 	print "    $abiold\n" if not -f "$abiold"; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	# Exit if the ABI files are missing, but return status based on whether | 
					
						
							|  |  |  | 	# skip ABI was indicated. | 
					
						
							|  |  |  | 	if ("$abiskip" eq "1") { | 
					
						
							|  |  |  | 		exit(0); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		exit(1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | my %symbols; | 
					
						
							|  |  |  | my %symbols_ignore; | 
					
						
							|  |  |  | my %modules_ignore; | 
					
						
							|  |  |  | my %module_syms; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # See if we have any ignores | 
					
						
							|  |  |  | my $ignore = 0; | 
					
						
							|  |  |  | print "    Reading symbols/modules to ignore..."; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | for $file ("abi-blacklist") { | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | 	if (-f $file) { | 
					
						
							|  |  |  | 		open(IGNORE, "< $file") or | 
					
						
							|  |  |  | 			die "Could not open $file"; | 
					
						
							|  |  |  | 		while (<IGNORE>) { | 
					
						
							|  |  |  | 			chomp; | 
					
						
							|  |  |  | 			if ($_ =~ m/M: (.*)/) { | 
					
						
							|  |  |  | 				$modules_ignore{$1} = 1; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				$symbols_ignore{$_} = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			$ignore++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		close(IGNORE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | print "read $ignore symbols/modules.\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sub is_ignored($$) { | 
					
						
							|  |  |  | 	my ($mod, $sym) = @_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	die "Missing module name in is_ignored()" if not defined($mod); | 
					
						
							|  |  |  | 	die "Missing symbol name in is_ignored()" if not defined($sym); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (defined($symbols_ignore{$sym}) or defined($modules_ignore{$mod})) { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Read new syms first | 
					
						
							| 
									
										
										
										
											2018-03-21 13:27:31 +03:00
										 |  |  | print "    Reading new symbols ($abistr)..."; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | $count = 0; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | open(NEW, "< $abinew") or | 
					
						
							|  |  |  | 	die "Could not open $abinew"; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | while (<NEW>) { | 
					
						
							|  |  |  | 	chomp; | 
					
						
							|  |  |  | 	m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; | 
					
						
							|  |  |  | 	$symbols{$4}{'type'} = $1; | 
					
						
							|  |  |  | 	$symbols{$4}{'loc'} = $2; | 
					
						
							|  |  |  | 	$symbols{$4}{'hash'} = $3; | 
					
						
							|  |  |  | 	$module_syms{$2} = 0; | 
					
						
							|  |  |  | 	$count++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | close(NEW); | 
					
						
							|  |  |  | print "read $count symbols.\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Now the old symbols, checking for missing ones | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | print "    Reading old symbols..."; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | $count = 0; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | open(OLD, "< $abiold") or | 
					
						
							|  |  |  | 	die "Could not open $abiold"; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | while (<OLD>) { | 
					
						
							|  |  |  | 	chomp; | 
					
						
							|  |  |  | 	m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; | 
					
						
							|  |  |  | 	$symbols{$4}{'old_type'} = $1; | 
					
						
							|  |  |  | 	$symbols{$4}{'old_loc'} = $2; | 
					
						
							|  |  |  | 	$symbols{$4}{'old_hash'} = $3; | 
					
						
							|  |  |  | 	$count++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | close(OLD); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print "read $count symbols.\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print "II: Checking for missing symbols in new ABI..."; | 
					
						
							|  |  |  | $count = 0; | 
					
						
							|  |  |  | foreach $sym (keys(%symbols)) { | 
					
						
							|  |  |  | 	if (!defined($symbols{$sym}{'type'})) { | 
					
						
							|  |  |  | 		print "\n" if not $count; | 
					
						
							|  |  |  | 		printf("    MISS : %s%s\n", $sym, | 
					
						
							|  |  |  | 			is_ignored($symbols{$sym}{'old_loc'}, $sym) ? " (ignored)" : ""); | 
					
						
							|  |  |  | 		$count++ if !is_ignored($symbols{$sym}{'old_loc'}, $sym); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | print "    " if $count; | 
					
						
							|  |  |  | print "found $count missing symbols\n"; | 
					
						
							|  |  |  | if ($count) { | 
					
						
							|  |  |  | 	print "$EE Symbols gone missing (what did you do!?!)\n"; | 
					
						
							|  |  |  | 	$errors++; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print "II: Checking for new symbols in new ABI..."; | 
					
						
							|  |  |  | $count = 0; | 
					
						
							|  |  |  | foreach $sym (keys(%symbols)) { | 
					
						
							|  |  |  | 	if (!defined($symbols{$sym}{'old_type'})) { | 
					
						
							|  |  |  | 		print "\n" if not $count; | 
					
						
							|  |  |  | 		print "    NEW : $sym\n"; | 
					
						
							|  |  |  | 		$count++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | print "    " if $count; | 
					
						
							|  |  |  | print "found $count new symbols\n"; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:48:31 +03:00
										 |  |  | if ($count) { | 
					
						
							|  |  |  | 	print "WW: Found new symbols. Not recommended unless ABI was bumped\n"; | 
					
						
							| 
									
										
										
										
											2017-03-24 14:27:58 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print "II: Checking for changes to ABI...\n"; | 
					
						
							|  |  |  | $count = 0; | 
					
						
							|  |  |  | my $moved = 0; | 
					
						
							|  |  |  | my $changed_type = 0; | 
					
						
							|  |  |  | my $changed_hash = 0; | 
					
						
							|  |  |  | foreach $sym (keys(%symbols)) { | 
					
						
							|  |  |  | 	if (!defined($symbols{$sym}{'old_type'}) or | 
					
						
							|  |  |  | 	    !defined($symbols{$sym}{'type'})) { | 
					
						
							|  |  |  | 		next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Changes in location don't hurt us, but log it anyway | 
					
						
							|  |  |  | 	if ($symbols{$sym}{'loc'} ne $symbols{$sym}{'old_loc'}) { | 
					
						
							|  |  |  | 		printf("    MOVE : %-40s : %s => %s\n", $sym, $symbols{$sym}{'old_loc'}, | 
					
						
							|  |  |  | 			$symbols{$sym}{'loc'}); | 
					
						
							|  |  |  | 		$moved++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Changes to export type are only bad if new type isn't | 
					
						
							|  |  |  | 	# EXPORT_SYMBOL. Changing things to GPL are bad. | 
					
						
							|  |  |  | 	if ($symbols{$sym}{'type'} ne $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) | 
					
						
							|  |  |  | 			? " (ignored)" : ""); | 
					
						
							|  |  |  | 		$changed_type++ if $symbols{$sym}{'type'} ne "EXPORT_SYMBOL" | 
					
						
							|  |  |  | 			and !is_ignored($symbols{$sym}{'loc'}, $sym); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Changes to the hash are always bad | 
					
						
							|  |  |  | 	if ($symbols{$sym}{'hash'} ne $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) | 
					
						
							|  |  |  | 			? " (ignored)" : ""); | 
					
						
							|  |  |  | 		$changed_hash++ if !is_ignored($symbols{$sym}{'loc'}, $sym); | 
					
						
							|  |  |  | 		$module_syms{$symbols{$sym}{'loc'}}++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print "WW: $moved symbols changed location\n" if $moved; | 
					
						
							|  |  |  | print "$EE $changed_type symbols changed export type and weren't ignored\n" if $changed_type; | 
					
						
							|  |  |  | print "$EE $changed_hash symbols changed hash and weren't ignored\n" if $changed_hash; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $errors++ if $changed_hash or $changed_type; | 
					
						
							|  |  |  | if ($changed_hash) { | 
					
						
							|  |  |  | 	print "II: Module hash change summary...\n"; | 
					
						
							|  |  |  | 	foreach $mod (sort { $module_syms{$b} <=> $module_syms{$a} } keys %module_syms) { | 
					
						
							|  |  |  | 		next if ! $module_syms{$mod}; | 
					
						
							|  |  |  | 		printf("    %-40s: %d\n", $mod, $module_syms{$mod}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print "II: Done\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if ($errors) { | 
					
						
							|  |  |  | 	exit($fail_exit); | 
					
						
							|  |  |  | } else { | 
					
						
							|  |  |  | 	exit(0); | 
					
						
							|  |  |  | } |