1#!/usr/bin/perl -w 2# 3# headers_check.pl execute a number of trivial consistency checks 4# 5# Usage: headers_check.pl dir arch [files...] 6# dir: dir to look for included files 7# arch: architecture 8# files: list of files to check 9# 10# The script reads the supplied files line by line and: 11# 12# 1) for each include statement it checks if the 13# included file actually exists. 14# Only include files located in asm* and linux* are checked. 15# The rest are assumed to be system include files. 16# 17# 2) It is checked that prototypes does not use "extern" 18# 19# 3) Check for leaked CONFIG_ symbols 20 21use strict; 22use File::Basename; 23 24my ($dir, $arch, @files) = @ARGV; 25 26my $ret = 0; 27my $line; 28my $lineno = 0; 29my $filename; 30 31foreach my $file (@files) { 32 $filename = $file; 33 34 open(my $fh, '<', $filename) 35 or die "$filename: $!\n"; 36 $lineno = 0; 37 while ($line = <$fh>) { 38 $lineno++; 39 &check_include(); 40 &check_asm_types(); 41 &check_sizetypes(); 42 &check_declarations(); 43 # Dropped for now. Too much noise &check_config(); 44 } 45 close $fh; 46} 47exit $ret; 48 49sub check_include 50{ 51 if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) { 52 my $inc = $1; 53 my $found; 54 $found = stat($dir . "/" . $inc); 55 if (!$found) { 56 $inc =~ s#asm/#asm-$arch/#; 57 $found = stat($dir . "/" . $inc); 58 } 59 if (!$found) { 60 printf STDERR "$filename:$lineno: included file '$inc' is not exported\n"; 61 $ret = 1; 62 } 63 } 64} 65 66sub check_declarations 67{ 68 # soundcard.h is what it is 69 if ($line =~ m/^void seqbuf_dump\(void\);/) { 70 return; 71 } 72 if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) { 73 printf STDERR "$filename:$lineno: " . 74 "userspace cannot reference function or " . 75 "variable defined in the kernel\n"; 76 } 77} 78 79sub check_config 80{ 81 if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) { 82 printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n"; 83 } 84} 85 86my $linux_asm_types; 87sub check_asm_types 88{ 89 if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 90 return; 91 } 92 if ($lineno == 1) { 93 $linux_asm_types = 0; 94 } elsif ($linux_asm_types >= 1) { 95 return; 96 } 97 if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) { 98 $linux_asm_types = 1; 99 printf STDERR "$filename:$lineno: " . 100 "include of <linux/types.h> is preferred over <asm/types.h>\n" 101 # Warn until headers are all fixed 102 #$ret = 1; 103 } 104} 105 106my $linux_types; 107my %import_stack = (); 108sub check_include_typesh 109{ 110 my $path = $_[0]; 111 my $import_path; 112 113 my $fh; 114 my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path); 115 for my $possible ( @file_paths ) { 116 if (not $import_stack{$possible} and open($fh, '<', $possible)) { 117 $import_path = $possible; 118 $import_stack{$import_path} = 1; 119 last; 120 } 121 } 122 if (eof $fh) { 123 return; 124 } 125 126 my $line; 127 while ($line = <$fh>) { 128 if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 129 $linux_types = 1; 130 last; 131 } 132 if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 133 check_include_typesh($included); 134 } 135 } 136 close $fh; 137 delete $import_stack{$import_path}; 138} 139 140sub check_sizetypes 141{ 142 if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 143 return; 144 } 145 if ($lineno == 1) { 146 $linux_types = 0; 147 } elsif ($linux_types >= 1) { 148 return; 149 } 150 if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 151 $linux_types = 1; 152 return; 153 } 154 if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 155 check_include_typesh($included); 156 } 157 if ($line =~ m/__[us](8|16|32|64)\b/) { 158 printf STDERR "$filename:$lineno: " . 159 "found __[us]{8,16,32,64} type " . 160 "without #include <linux/types.h>\n"; 161 $linux_types = 2; 162 # Warn until headers are all fixed 163 #$ret = 1; 164 } 165} 166