1#!/usr/bin/env perl 2# SPDX-License-Identifier: GPL-2.0 3# 4# headers_check.pl execute a number of trivial consistency checks 5# 6# Usage: headers_check.pl dir [files...] 7# dir: dir to look for included files 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, @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_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 printf STDERR "$filename:$lineno: included file '$inc' is not exported\n"; 57 $ret = 1; 58 } 59 } 60} 61 62sub check_declarations 63{ 64 # soundcard.h is what it is 65 if ($line =~ m/^void seqbuf_dump\(void\);/) { 66 return; 67 } 68 # drm headers are being C++ friendly 69 if ($line =~ m/^extern "C"/) { 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 $ret = 1; 77 } 78} 79 80sub check_config 81{ 82 if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) { 83 printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n"; 84 } 85} 86 87my $linux_asm_types; 88sub check_asm_types 89{ 90 if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 91 return; 92 } 93 if ($lineno == 1) { 94 $linux_asm_types = 0; 95 } elsif ($linux_asm_types >= 1) { 96 return; 97 } 98 if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) { 99 $linux_asm_types = 1; 100 printf STDERR "$filename:$lineno: " . 101 "include of <linux/types.h> is preferred over <asm/types.h>\n"; 102 $ret = 1; 103 } 104} 105