KernelNewbies
  • Comments
  • Immutable Page
  • Menu
    • Navigation
    • RecentChanges
    • FindPage
    • Local Site Map
    • Help
    • HelpContents
    • HelpOnMoinWikiSyntax
    • Display
    • Attachments
    • Info
    • Raw Text
    • Print View
    • Edit
    • Load
    • Save
  • Login

Kernel Hacking

  • Frontpage

  • Kernel Hacking

  • Kernel Documentation

  • Kernel Glossary

  • FAQ

  • Found a bug?

  • Kernel Changelog

  • Upstream Merge Guide

Projects

  • KernelJanitors

  • KernelMentors

  • KernelProjects

Community

  • Why a community?

  • Regional Kernelnewbies

  • Personal Pages

  • Upcoming Events

References

  • Mailing Lists

  • Related Sites

  • Programming Links

Wiki

  • Recent Changes

  • Site Editors

  • Side Bar

  • Tips for Editors

  • Hosted by WikiWall

Navigation

  • RecentChanges
  • FindPage
  • HelpContents
KernelNewbies:
  • attachment:kj-devel.pl of MigratingInProgress/scripts

Attachment 'kj-devel.pl'

Download

Toggle line numbers
   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.
  • [get | view] (2017-12-30 01:15:02, 12.0 KB) [[attachment:kj-devel.pl]]
  • [get | view] (2017-12-30 01:15:02, 5.3 KB) [[attachment:kj.pl]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.

  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01