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