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