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