1
0

abi-check 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #!/usr/bin/perl -w
  2. my $abinew = shift;
  3. my $abiold = shift;
  4. my $skipabi = shift;
  5. # to catch multiple abi-prev-* files being passed in
  6. die "invalid value for skipabi parameter\n"
  7. if (defined($skipabi) && $skipabi !~ /^[01]$/);
  8. $abinew =~ /abi-(.*)/;
  9. my $abistr = $1;
  10. $abiold =~ /abi-prev-(.*)/;
  11. my $prev_abistr = $1;
  12. my $fail_exit = 1;
  13. my $EE = "EE:";
  14. my $errors = 0;
  15. my $abiskip = 0;
  16. my $count;
  17. print "II: Checking ABI...\n";
  18. if ($skipabi) {
  19. print "WW: Explicitly asked to ignore ABI, running in no-fail mode\n";
  20. $fail_exit = 0;
  21. $abiskip = 1;
  22. $EE = "WW:";
  23. }
  24. if ($prev_abistr ne $abistr) {
  25. print "II: Different ABI's, running in no-fail mode\n";
  26. $fail_exit = 0;
  27. $EE = "WW:";
  28. }
  29. if (not -f "$abinew" or not -f "$abiold") {
  30. print "EE: Previous or current ABI file missing!\n";
  31. print " $abinew\n" if not -f "$abinew";
  32. print " $abiold\n" if not -f "$abiold";
  33. # Exit if the ABI files are missing, but return status based on whether
  34. # skip ABI was indicated.
  35. if ("$abiskip" eq "1") {
  36. exit(0);
  37. } else {
  38. exit(1);
  39. }
  40. }
  41. my %symbols;
  42. my %symbols_ignore;
  43. my %modules_ignore;
  44. my %module_syms;
  45. # See if we have any ignores
  46. my $ignore = 0;
  47. print " Reading symbols/modules to ignore...";
  48. for $file ("abi-blacklist") {
  49. if (-f $file) {
  50. open(IGNORE, "< $file") or
  51. die "Could not open $file";
  52. while (<IGNORE>) {
  53. chomp;
  54. if ($_ =~ m/M: (.*)/) {
  55. $modules_ignore{$1} = 1;
  56. } else {
  57. $symbols_ignore{$_} = 1;
  58. }
  59. $ignore++;
  60. }
  61. close(IGNORE);
  62. }
  63. }
  64. print "read $ignore symbols/modules.\n";
  65. sub is_ignored($$) {
  66. my ($mod, $sym) = @_;
  67. die "Missing module name in is_ignored()" if not defined($mod);
  68. die "Missing symbol name in is_ignored()" if not defined($sym);
  69. if (defined($symbols_ignore{$sym}) or defined($modules_ignore{$mod})) {
  70. return 1;
  71. }
  72. return 0;
  73. }
  74. # Read new syms first
  75. print " Reading new symbols ($abistr)...";
  76. $count = 0;
  77. open(NEW, "< $abinew") or
  78. die "Could not open $abinew";
  79. while (<NEW>) {
  80. chomp;
  81. m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/;
  82. $symbols{$4}{'type'} = $1;
  83. $symbols{$4}{'loc'} = $2;
  84. $symbols{$4}{'hash'} = $3;
  85. $module_syms{$2} = 0;
  86. $count++;
  87. }
  88. close(NEW);
  89. print "read $count symbols.\n";
  90. # Now the old symbols, checking for missing ones
  91. print " Reading old symbols...";
  92. $count = 0;
  93. open(OLD, "< $abiold") or
  94. die "Could not open $abiold";
  95. while (<OLD>) {
  96. chomp;
  97. m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/;
  98. $symbols{$4}{'old_type'} = $1;
  99. $symbols{$4}{'old_loc'} = $2;
  100. $symbols{$4}{'old_hash'} = $3;
  101. $count++;
  102. }
  103. close(OLD);
  104. print "read $count symbols.\n";
  105. print "II: Checking for missing symbols in new ABI...";
  106. $count = 0;
  107. foreach $sym (keys(%symbols)) {
  108. if (!defined($symbols{$sym}{'type'})) {
  109. print "\n" if not $count;
  110. printf(" MISS : %s%s\n", $sym,
  111. is_ignored($symbols{$sym}{'old_loc'}, $sym) ? " (ignored)" : "");
  112. $count++ if !is_ignored($symbols{$sym}{'old_loc'}, $sym);
  113. }
  114. }
  115. print " " if $count;
  116. print "found $count missing symbols\n";
  117. if ($count) {
  118. print "$EE Symbols gone missing (what did you do!?!)\n";
  119. $errors++;
  120. }
  121. print "II: Checking for new symbols in new ABI...";
  122. $count = 0;
  123. foreach $sym (keys(%symbols)) {
  124. if (!defined($symbols{$sym}{'old_type'})) {
  125. print "\n" if not $count;
  126. print " NEW : $sym\n";
  127. $count++;
  128. }
  129. }
  130. print " " if $count;
  131. print "found $count new symbols\n";
  132. if ($count) {
  133. print "WW: Found new symbols. Not recommended unless ABI was bumped\n";
  134. }
  135. print "II: Checking for changes to ABI...\n";
  136. $count = 0;
  137. my $moved = 0;
  138. my $changed_type = 0;
  139. my $changed_hash = 0;
  140. foreach $sym (keys(%symbols)) {
  141. if (!defined($symbols{$sym}{'old_type'}) or
  142. !defined($symbols{$sym}{'type'})) {
  143. next;
  144. }
  145. # Changes in location don't hurt us, but log it anyway
  146. if ($symbols{$sym}{'loc'} ne $symbols{$sym}{'old_loc'}) {
  147. printf(" MOVE : %-40s : %s => %s\n", $sym, $symbols{$sym}{'old_loc'},
  148. $symbols{$sym}{'loc'});
  149. $moved++;
  150. }
  151. # Changes to export type are only bad if new type isn't
  152. # EXPORT_SYMBOL. Changing things to GPL are bad.
  153. if ($symbols{$sym}{'type'} ne $symbols{$sym}{'old_type'}) {
  154. printf(" TYPE : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_type'}.
  155. $symbols{$sym}{'type'}, is_ignored($symbols{$sym}{'loc'}, $sym)
  156. ? " (ignored)" : "");
  157. $changed_type++ if $symbols{$sym}{'type'} ne "EXPORT_SYMBOL"
  158. and !is_ignored($symbols{$sym}{'loc'}, $sym);
  159. }
  160. # Changes to the hash are always bad
  161. if ($symbols{$sym}{'hash'} ne $symbols{$sym}{'old_hash'}) {
  162. printf(" HASH : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_hash'},
  163. $symbols{$sym}{'hash'}, is_ignored($symbols{$sym}{'loc'}, $sym)
  164. ? " (ignored)" : "");
  165. $changed_hash++ if !is_ignored($symbols{$sym}{'loc'}, $sym);
  166. $module_syms{$symbols{$sym}{'loc'}}++;
  167. }
  168. }
  169. print "WW: $moved symbols changed location\n" if $moved;
  170. print "$EE $changed_type symbols changed export type and weren't ignored\n" if $changed_type;
  171. print "$EE $changed_hash symbols changed hash and weren't ignored\n" if $changed_hash;
  172. $errors++ if $changed_hash or $changed_type;
  173. if ($changed_hash) {
  174. print "II: Module hash change summary...\n";
  175. foreach $mod (sort { $module_syms{$b} <=> $module_syms{$a} } keys %module_syms) {
  176. next if ! $module_syms{$mod};
  177. printf(" %-40s: %d\n", $mod, $module_syms{$mod});
  178. }
  179. }
  180. print "II: Done\n";
  181. if ($errors) {
  182. exit($fail_exit);
  183. } else {
  184. exit(0);
  185. }