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