Attachment 'kj-devel.pl'
Download 1 #!/usr/bin/perl -w
2 #
3 # An automated kernel janitor.
4 # (c) 2001, Dave Jones. <davej@suse.de>, with invaluable
5 # perl assistance from Rob Andrews <nine@impure.org.uk>
6 # Various code also inspired from hundreds of other perl scripts.
7 #
8 # Additional functionality added by The kerneljanitors.org team :)
9 #
10 # Licensed under the terms of the GNU GPL License version 2
11 #
12 # $Id: kj-devel.pl,v 1.5 2005/03/23 13:45:07 domen Exp $
13 #
14 # 1.0 Initial version.
15 # 1.1 Spinlock balancing checker improved.
16 # Vicente Feito Added options posibility
17 # <vicente.feito@gmail.com> New loader function to fix multiple files load
18 # Changed the storage structure, from array to hashes
19 # include files processing (local and tree referred)
20 # Added more checks based on DO's and DONT's
21 # Skip comments on source files(C and C++ Style)
22 # Some trivial fixes and cleanup
23 # spinlock code rewrite
24 # Fixed line numbers
25 # Fixed panic() checks on files that are not drivers
26 # ioremap()/iounmap() balance check
27
28 use strict;
29 use Getopt::Long;
30
31 my @lines = ();
32 my $linesinfile=0;
33 my $module; #flag, mantains the module_init/_exit
34 my $comment = 0;
35
36 my ($includes, $nospinlocks, $nomodules, $pathinclude);
37 my $linenr;
38 my %filenames = ();
39 my @archs = @ARGV;
40 my $include;
41 chomp($pathinclude = `uname -r`);
42
43
44 die "$0 <--includes> <--nospinlocks> <--nomodules> <file1 file2 file...>
45 --includes Checks inside the #include files
46 --nospinlocks Don't Check spinlocks, default is yes
47 --nomodules In case you're not building a module
48 file1 file2 ... The files you want to check\n" unless @ARGV > 0;
49
50 GetOptions("includes" => \$includes,
51 "nospinlocks" => \$nospinlocks,
52 "nomodules" => \$nomodules);
53
54 if ($includes) {
55 shift @archs;
56 }
57 if ($nospinlocks) {
58 shift @archs;
59 }
60 if ($nomodules) {
61 shift @archs;
62 }
63
64 #Here's where everything starts
65 loader();
66
67 sub loader {
68 foreach my $filename (@archs) {
69 open(FILE, "<$filename") or "Unable to open $filename $!" and next;
70 while(<FILE>) {
71 #Add the includes files if the --includes option is given
72 if ($includes and $_ =~ /#include[ |\t]?([<|"])([^(>|")]*)/) {
73 if ($1 eq "\"") {
74 $include = giveLocal($filename, $2);
75
76 } else {
77 $include = "/lib/modules/$pathinclude/build/include/$2";
78 }
79 #Check if the file isn't already there, if it's not, push it
80 if (not exists($filenames{$include})) {
81 push @archs, $include;
82 }
83 }
84
85 #Push the lines of each file inside the array of that file in the hash
86 push @{$filenames{$filename}}, $_;
87 }
88 close(FILE);
89 }
90 process();
91 }
92
93 sub check_pci_enable_device {
94 my ($used, $filename) = @_;
95 my $currentlinenr;
96 foreach my $current (@lines) {
97 if ($current=~/pci_enable_device/) {
98 if ($currentlinenr < $used) {
99 print "Should be ok, called on line $currentlinenr\n";
100 print "$filename:$currentlinenr:$current\n";
101 return;
102 }
103 }
104 $currentlinenr++;
105 }
106 }
107
108 sub process {
109 my (%locks, %locks_irq, %locks_bh, %ioremap);
110 my $comment = 0;
111 my $spinlockwarn=0;
112 my $lookspci=0;
113 my $drvdata; #this allow to check MODULE_ macros
114
115 foreach my $filename (@archs) {
116 $linenr = 1;
117 $linesinfile = $#{$filenames{$filename}}+1;
118
119 #This is dirty, but just in order to keep check_* working
120 #until I clean those too.
121 @lines = @{$filenames{$filename}};
122
123 print "\n" . "x"x15 . " $filename " . "x"x15 ."\n\n";
124 foreach my $line (@{$filenames{$filename}}) {
125 $drvdata = 4;
126
127 #This code skips comments.
128 if ($line=~/^\/\//) {
129 $linenr++;
130 next;
131 }
132 $comment = 1 if ($line=~/(^|\s+)\/\*/);
133 if ($comment) {
134 $comment = 0 if ($line=~/\*\//);
135 $linenr++;
136 next;
137 }
138 chomp($line);
139
140
141 if ($line=~/static const char.*__initdata/) {
142 print "const & __initdata in string def. Remove const.\n";
143 print "$filename:$linenr:$line\n\n";
144 }
145
146 if ($line=~/\(struct netdev_private \*\)/) {
147 print "Unnecessary cast.\n";
148 print "$filename:$linenr:$line\n\n";
149 }
150
151 if ($line=~/netif_rx/) {
152 print "Net drivers should set dev->last_rx immediately after netif_rx\n";
153 print "Also make sure the skb isn't referenced after giving it to netif_rx\n";
154 print "$filename:$linenr:$line\n\n";
155 }
156
157 if ($line=~/(GET|MOD_(INC|DEC))_USE_COUNT/) {
158 print "MOD_{INC,DEC}_USE_COUNT and GET_USE_COUNT are deprecated for 2.6: see the module-init-tools FAQ\n";
159 print "$filename:$linenr:$line\n\n";
160 }
161
162 if ($line=~/SET_MODULE_OWNER/) {
163 print "SET_MODULE_OWNER is useless for 2.6: see the module-init-tools FAQ\n";
164 print "$filename:$linenr:$line\n\n";
165 }
166
167 if ($line=~/sleep_on/) {
168 print "Using sleep_on derivative, is racy. consider using wait_event instead\n";
169 print "$filename:$linenr:$line\n\n";
170 }
171
172 if ($line=~/check_region/) {
173 print "Using check_region, is racy, use just request_region and check for its return.\n";
174 print "$filename:$linenr:$line\n\n";
175 }
176
177 if ($line=~/check_mem_region/) {
178 print "Using check_mem_region, is racy, use just request_mem_region and check for its return.\n";
179 print "$filename:$linenr:$line\n\n";
180 }
181
182 if ($line=~/pdev-\>irq/) {
183 print "Make sure pci_enable_device before reading irq\n";
184 check_pci_enable_device($linenr, $filename);
185 print "$filename:$linenr:$line\n\n";
186 }
187
188 if (($lookspci==0) and ($line=~/pci_/)) {
189 $lookspci=1;
190 print "Looks like a PCI driver. Make sure it uses pci_enable_device.\n";
191 check_pci_enable_device($linenr, $filename);
192 print "$filename:$linenr:$line\n\n";
193 }
194
195 if ($line=~/pdev-\>resource/) {
196 print "Make sure pci_enable_device --before-- reading resource\n";
197 check_pci_enable_device($linenr, $filename);
198 print "$filename:$linenr:$line\n\n";
199 }
200
201 if ($line=~/pcibios_/) {
202 print "Uses obsolete pcibios_xxx functions.\n";
203 print "$filename:$linenr:$line\n\n";
204 }
205
206 if ($line=~/save_flags_cli/) {
207 print "Use local_irq_save instead.\n";
208 print "$filename:$linenr:$line\n\n";
209 }
210
211 if ($line=~/isa_{read,write}{b,w,l}/) {
212 print "Use ioremap instead of isa_read/write functions.\n";
213 print "$filename:$linenr:$line\n\n";
214 }
215
216 if ($line=~/current-\>state/) {
217 print "Bad. Should use set_current_state.\n";
218 print "$filename:$linenr:$line\n\n";
219 }
220
221
222 if ($line=~/loops_per_sec/) {
223 print "Warning: loops_per_sec may change..\n";
224 print "$filename:$linenr:$line\n\n";
225 }
226
227 if ($line=~/if.*dev-\>mem_start/) {
228 if (($line!~/0xffffffff/) or ($line!~/-1/)) {
229 print "Should check for 0xffffffff too.\n";
230 print "$filename:$linenr:$line\n\n";
231 }
232 }
233
234 if (($spinlockwarn==0) and
235 (($line=~/cli\(\)/) or
236 ($line=~/sti\(\)/) or
237 ($line=~/lock_kernel/))){
238 $spinlockwarn=1;
239 print "Consider using spinlocks.\n";
240 print "$filename:$linenr:$line\n\n";
241 }
242
243 if ($line=~/return( |\t)*E[^(]*$/) {
244 print "Should be return -E ?";
245 print "$filename:$linenr:$line\n\n";
246 }
247
248 if (not $nospinlocks and $line=~/(^|[^_])spin_lock\(&?(.*)\);/) {
249 #add that one
250 push @{$locks{$2}}, $linenr;
251 }
252 if (not $nospinlocks and $line=~/(^|[^_])spin_unlock\(&?(.*)\);/) {
253
254 if (not exists($locks{$2}) or
255 (exists($locks{$2}) and @{$locks{$2}} == 0)) {
256 print "Unlocking a lock that hasn't been acquired ".
257 "yet (could be a false positive) - Line:$linenr\n\n";
258 } else {
259 #get rid of the last one
260 pop @{$locks{$2}};
261 }
262 }
263
264 if (not $nospinlocks and $line=~/(^|[^_])spin_lock_irqsave\(&?(.*)\);/) {
265 push @{$locks_irq{$2}}, $linenr;
266 }
267 if (not $nospinlocks and
268 $line=~/(^|[^_])spin_unlock_irqrestore\(&?(.*)\);/) {
269
270 if (not exists($locks_irq{$2}) or
271 (exists($locks_irq{$2}) and @{$locks_irq{$2}} == 0)) {
272 print "Unlocking a lock that hasn't been acquired ".
273 "yet (could be a false positive) - Line:$linenr\n\n";
274 } else {
275 pop @{$locks_irq{$2}};
276 }
277 }
278
279 if (not $nospinlocks and $line=~/(^|[^_])spin_lock_bh\(&?(.*)\);/) {
280 push @{$locks_bh{$2}}, $linenr;
281 }
282 if (not $nospinlocks and
283 $line=~/(^|[^_])spin_unlock_bh\(&?(.*)\);/) {
284
285 if (not exists($locks_bh{$2}) or
286 (exists($locks_bh{$2}) and @{$locks_bh{$2}} == 0)) {
287 print "Unlocking a lock that hasn't been acquired ".
288 "yet (could be a false positive) - Line:$linenr\n\n";
289 } else {
290 pop @{$locks_bh{$2}};
291 }
292 }
293
294 # ioremap() / iounmap()
295 if ($line=~/(^|[^_])ioremap\((.*),.*\);/) {
296 push @{$ioremap{$2}}, $linenr;
297 }
298 if ($line=~/(^|[^_])iounmap\((.*)\)/) {
299 if (not exists($ioremap{$2}) or
300 (exists($ioremap{$2}) and @{$ioremap{$2}} == 0)) {
301 print "Unmapping a region that hasn't been mapped ".
302 "yet (could be a false positive) - Line:$linenr\n\n";
303 } else {
304 pop @{$ioremap{$2}};
305 }
306 }
307
308 #we make sure it's a driver to check for panic
309 if (not $nomodules and $line=~/panic\((.*)\)/ and $line!~/^NORET_TYPE/) {
310 print "Device Drivers as a general rule should not call panic().\n";
311 print "$filename:$linenr:$line\n\n";
312 }
313 if ($line=~/save_flags(_cli)?\(\)/ or $line=~/restore_flags\(\)/) {
314 print "save_flags_* and restore flags should not be used.\n";
315 print "$filename:$linenr:$line\n\n";
316 }
317 if ($line=~/module_init\((.*)\)/ or $line=~/module_exit\((.*)\)/) {
318 $module = 1;
319 }
320 if ($line=~/MODULE_AUTHOR\(.*\)/ or
321 $line=~/MODULE_LICENSE\(.*\)/ or
322 $line=~/SUPPORTED_DEVICE\(.*\)/ or
323 $line=~/MODULE_DESCRIPTION\(.*\)/) {
324 $drvdata--;
325 }
326 if ($line=~/MODULE_PARM\(.*\)/) {
327 print "MODULE_PARM() has been replaced by module_param(name, type, perm).\n";
328 print "$filename:$linenr:$line\n\n";
329 }
330 if ($line=~/^#.*__SMP__/) {
331 print "__SMP__ is no longer used and it's going to dissapear soon.\n";
332 print "$filename:$linenr:$line\n\n";
333 }
334 if ($line=~/strtok\(.*\)/) {
335 print "strtok() is racy on smp, use strsep() instead.\n";
336 print "$filename:$linenr:$line\n\n";
337 }
338 if ($line=~/int 0x80/) {
339 print "Device Drivers should never use syscalls.\n";
340 print "$filename:$linenr:$line\n\n";
341 }
342 if ($line=~/\bproc_register\(.*\)/) {
343 print "proc_register() should be replaced with create_proc_entry().\n";
344 print "$filename:$linenr:$line\n\n";
345 }
346 if ($line=~/(const )?char ?\* ?\w+ ?= ?\".*\"/) {
347 print "Using foo[] is recommended over *foo: saves memory references & code\n";
348 print "$filename:$linenr:$line\n\n";
349 }
350 if ($line=~/memset\((.*),( *sizeof.*),( *\d+)\)/) {
351 print "Your memset parameters appears to be backwards\n";
352 print "$filename:$linenr:$line\n\n";
353 }
354 $linenr++;
355 }
356 #now we show the not unlocked ones
357 show_balance_results(0,%locks);
358 show_balance_results(0,%locks_bh);
359 show_balance_results(0,%locks_irq);
360 show_balance_results(1,%ioremap);
361
362 if (!$nomodules and !defined($module)) {
363 print "If you're building a module, note that you must use the".
364 " init mechanism, module_init() and module_exit().\n";
365 }
366 if (!$nomodules and $drvdata) {
367 print "MODULE_AUTHOR/MODULE_LICENSE/SUPPORTED_DEVICE/MODULE_DESCRIPTION".
368 " are now required.\n";
369 }
370 }
371 return 1;
372 }
373
374 #Returns the name of a local file given from an #include ""
375 #1st parm:the actual file being processed
376 #2nd parm:The file being included by include ""
377 sub giveLocal {
378 my ($include, $local) = @_;
379 $include = reverse($include);
380 my ($name, $path) = split(/\//, $include, 2);
381 return reverse($path)."/$local";
382 }
383
384 #This shows the function calls not balanced
385 sub show_balance_results {
386 my $flag = shift;
387 my %checks = @_;
388
389 foreach my $check (sort keys %checks) {
390 if (@{$checks{$check}}) {
391 if ($flag) {
392 print "ioremap($check) used and iounmap missing in line(s)".
393 "(maybe iounmapped before?) - Line:@{$checks{$check}}\n\n";
394 } else {
395 print "Lock ($check) obtained and not unlocked in line(s)".
396 "(maybe unlocked before?) - Line:@{$checks{$check}}\n\n";
397 }
398
399 }
400 }
401 }
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.