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