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 # drm headers are being C++ friendly 73 if ($line =~ m/^extern "C"/) { 74 return; 75 } 76 if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) { 77 printf STDERR "$filename:$lineno: " . 78 "userspace cannot reference function or " . 79 "variable defined in the kernel\n"; 80 } 81} 82 83sub check_config 84{ 85 if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) { 86 printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n"; 87 } 88} 89 90my $linux_asm_types; 91sub check_asm_types 92{ 93 if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 94 return; 95 } 96 if ($lineno == 1) { 97 $linux_asm_types = 0; 98 } elsif ($linux_asm_types >= 1) { 99 return; 100 } 101 if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) { 102 $linux_asm_types = 1; 103 printf STDERR "$filename:$lineno: " . 104 "include of <linux/types.h> is preferred over <asm/types.h>\n" 105 # Warn until headers are all fixed 106 #$ret = 1; 107 } 108} 109 110my $linux_types; 111my %import_stack = (); 112sub check_include_typesh 113{ 114 my $path = $_[0]; 115 my $import_path; 116 117 my $fh; 118 my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path); 119 for my $possible ( @file_paths ) { 120 if (not $import_stack{$possible} and open($fh, '<', $possible)) { 121 $import_path = $possible; 122 $import_stack{$import_path} = 1; 123 last; 124 } 125 } 126 if (eof $fh) { 127 return; 128 } 129 130 my $line; 131 while ($line = <$fh>) { 132 if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 133 $linux_types = 1; 134 last; 135 } 136 if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 137 check_include_typesh($included); 138 } 139 } 140 close $fh; 141 delete $import_stack{$import_path}; 142} 143 144sub check_sizetypes 145{ 146 if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 147 return; 148 } 149 if ($lineno == 1) { 150 $linux_types = 0; 151 } elsif ($linux_types >= 1) { 152 return; 153 } 154 if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 155 $linux_types = 1; 156 return; 157 } 158 if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 159 check_include_typesh($included); 160 } 161 if ($line =~ m/__[us](8|16|32|64)\b/) { 162 printf STDERR "$filename:$lineno: " . 163 "found __[us]{8,16,32,64} type " . 164 "without #include <linux/types.h>\n"; 165 $linux_types = 2; 166 # Warn until headers are all fixed 167 #$ret = 1; 168 } 169} 170