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