150a48340SMasahiro Yamada#!/usr/bin/env perl 250a48340SMasahiro Yamada# SPDX-License-Identifier: GPL-2.0 350a48340SMasahiro Yamada# 450a48340SMasahiro Yamada# headers_check.pl execute a number of trivial consistency checks 550a48340SMasahiro Yamada# 6*d67393f4SGeert Uytterhoeven# Usage: headers_check.pl dir [files...] 750a48340SMasahiro Yamada# dir: dir to look for included files 850a48340SMasahiro Yamada# files: list of files to check 950a48340SMasahiro Yamada# 1050a48340SMasahiro Yamada# The script reads the supplied files line by line and: 1150a48340SMasahiro Yamada# 1250a48340SMasahiro Yamada# 1) for each include statement it checks if the 1350a48340SMasahiro Yamada# included file actually exists. 1450a48340SMasahiro Yamada# Only include files located in asm* and linux* are checked. 1550a48340SMasahiro Yamada# The rest are assumed to be system include files. 1650a48340SMasahiro Yamada# 1750a48340SMasahiro Yamada# 2) It is checked that prototypes does not use "extern" 1850a48340SMasahiro Yamada# 1950a48340SMasahiro Yamada# 3) Check for leaked CONFIG_ symbols 2050a48340SMasahiro Yamada 2150a48340SMasahiro Yamadause warnings; 2250a48340SMasahiro Yamadause strict; 2350a48340SMasahiro Yamadause File::Basename; 2450a48340SMasahiro Yamada 25*d67393f4SGeert Uytterhoevenmy ($dir, @files) = @ARGV; 2650a48340SMasahiro Yamada 2750a48340SMasahiro Yamadamy $ret = 0; 2850a48340SMasahiro Yamadamy $line; 2950a48340SMasahiro Yamadamy $lineno = 0; 3050a48340SMasahiro Yamadamy $filename; 3150a48340SMasahiro Yamada 3250a48340SMasahiro Yamadaforeach my $file (@files) { 3350a48340SMasahiro Yamada $filename = $file; 3450a48340SMasahiro Yamada 3550a48340SMasahiro Yamada open(my $fh, '<', $filename) 3650a48340SMasahiro Yamada or die "$filename: $!\n"; 3750a48340SMasahiro Yamada $lineno = 0; 3850a48340SMasahiro Yamada while ($line = <$fh>) { 3950a48340SMasahiro Yamada $lineno++; 4050a48340SMasahiro Yamada &check_include(); 4150a48340SMasahiro Yamada &check_asm_types(); 4250a48340SMasahiro Yamada &check_sizetypes(); 4350a48340SMasahiro Yamada &check_declarations(); 4450a48340SMasahiro Yamada # Dropped for now. Too much noise &check_config(); 4550a48340SMasahiro Yamada } 4650a48340SMasahiro Yamada close $fh; 4750a48340SMasahiro Yamada} 4850a48340SMasahiro Yamadaexit $ret; 4950a48340SMasahiro Yamada 5050a48340SMasahiro Yamadasub check_include 5150a48340SMasahiro Yamada{ 5250a48340SMasahiro Yamada if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) { 5350a48340SMasahiro Yamada my $inc = $1; 5450a48340SMasahiro Yamada my $found; 5550a48340SMasahiro Yamada $found = stat($dir . "/" . $inc); 5650a48340SMasahiro Yamada if (!$found) { 5750a48340SMasahiro Yamada printf STDERR "$filename:$lineno: included file '$inc' is not exported\n"; 5850a48340SMasahiro Yamada $ret = 1; 5950a48340SMasahiro Yamada } 6050a48340SMasahiro Yamada } 6150a48340SMasahiro Yamada} 6250a48340SMasahiro Yamada 6350a48340SMasahiro Yamadasub check_declarations 6450a48340SMasahiro Yamada{ 6550a48340SMasahiro Yamada # soundcard.h is what it is 6650a48340SMasahiro Yamada if ($line =~ m/^void seqbuf_dump\(void\);/) { 6750a48340SMasahiro Yamada return; 6850a48340SMasahiro Yamada } 6950a48340SMasahiro Yamada # drm headers are being C++ friendly 7050a48340SMasahiro Yamada if ($line =~ m/^extern "C"/) { 7150a48340SMasahiro Yamada return; 7250a48340SMasahiro Yamada } 7350a48340SMasahiro Yamada if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) { 7450a48340SMasahiro Yamada printf STDERR "$filename:$lineno: " . 7550a48340SMasahiro Yamada "userspace cannot reference function or " . 7650a48340SMasahiro Yamada "variable defined in the kernel\n"; 7750a48340SMasahiro Yamada } 7850a48340SMasahiro Yamada} 7950a48340SMasahiro Yamada 8050a48340SMasahiro Yamadasub check_config 8150a48340SMasahiro Yamada{ 8250a48340SMasahiro Yamada if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) { 8350a48340SMasahiro Yamada printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n"; 8450a48340SMasahiro Yamada } 8550a48340SMasahiro Yamada} 8650a48340SMasahiro Yamada 8750a48340SMasahiro Yamadamy $linux_asm_types; 8850a48340SMasahiro Yamadasub check_asm_types 8950a48340SMasahiro Yamada{ 9050a48340SMasahiro Yamada if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 9150a48340SMasahiro Yamada return; 9250a48340SMasahiro Yamada } 9350a48340SMasahiro Yamada if ($lineno == 1) { 9450a48340SMasahiro Yamada $linux_asm_types = 0; 9550a48340SMasahiro Yamada } elsif ($linux_asm_types >= 1) { 9650a48340SMasahiro Yamada return; 9750a48340SMasahiro Yamada } 9850a48340SMasahiro Yamada if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) { 9950a48340SMasahiro Yamada $linux_asm_types = 1; 10050a48340SMasahiro Yamada printf STDERR "$filename:$lineno: " . 10150a48340SMasahiro Yamada "include of <linux/types.h> is preferred over <asm/types.h>\n" 10250a48340SMasahiro Yamada # Warn until headers are all fixed 10350a48340SMasahiro Yamada #$ret = 1; 10450a48340SMasahiro Yamada } 10550a48340SMasahiro Yamada} 10650a48340SMasahiro Yamada 10750a48340SMasahiro Yamadamy $linux_types; 10850a48340SMasahiro Yamadamy %import_stack = (); 10950a48340SMasahiro Yamadasub check_include_typesh 11050a48340SMasahiro Yamada{ 11150a48340SMasahiro Yamada my $path = $_[0]; 11250a48340SMasahiro Yamada my $import_path; 11350a48340SMasahiro Yamada 11450a48340SMasahiro Yamada my $fh; 11550a48340SMasahiro Yamada my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path); 11650a48340SMasahiro Yamada for my $possible ( @file_paths ) { 11750a48340SMasahiro Yamada if (not $import_stack{$possible} and open($fh, '<', $possible)) { 11850a48340SMasahiro Yamada $import_path = $possible; 11950a48340SMasahiro Yamada $import_stack{$import_path} = 1; 12050a48340SMasahiro Yamada last; 12150a48340SMasahiro Yamada } 12250a48340SMasahiro Yamada } 12350a48340SMasahiro Yamada if (eof $fh) { 12450a48340SMasahiro Yamada return; 12550a48340SMasahiro Yamada } 12650a48340SMasahiro Yamada 12750a48340SMasahiro Yamada my $line; 12850a48340SMasahiro Yamada while ($line = <$fh>) { 12950a48340SMasahiro Yamada if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 13050a48340SMasahiro Yamada $linux_types = 1; 13150a48340SMasahiro Yamada last; 13250a48340SMasahiro Yamada } 13350a48340SMasahiro Yamada if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 13450a48340SMasahiro Yamada check_include_typesh($included); 13550a48340SMasahiro Yamada } 13650a48340SMasahiro Yamada } 13750a48340SMasahiro Yamada close $fh; 13850a48340SMasahiro Yamada delete $import_stack{$import_path}; 13950a48340SMasahiro Yamada} 14050a48340SMasahiro Yamada 14150a48340SMasahiro Yamadasub check_sizetypes 14250a48340SMasahiro Yamada{ 14350a48340SMasahiro Yamada if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 14450a48340SMasahiro Yamada return; 14550a48340SMasahiro Yamada } 14650a48340SMasahiro Yamada if ($lineno == 1) { 14750a48340SMasahiro Yamada $linux_types = 0; 14850a48340SMasahiro Yamada } elsif ($linux_types >= 1) { 14950a48340SMasahiro Yamada return; 15050a48340SMasahiro Yamada } 15150a48340SMasahiro Yamada if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 15250a48340SMasahiro Yamada $linux_types = 1; 15350a48340SMasahiro Yamada return; 15450a48340SMasahiro Yamada } 15550a48340SMasahiro Yamada if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 15650a48340SMasahiro Yamada check_include_typesh($included); 15750a48340SMasahiro Yamada } 15850a48340SMasahiro Yamada if ($line =~ m/__[us](8|16|32|64)\b/) { 15950a48340SMasahiro Yamada printf STDERR "$filename:$lineno: " . 16050a48340SMasahiro Yamada "found __[us]{8,16,32,64} type " . 16150a48340SMasahiro Yamada "without #include <linux/types.h>\n"; 16250a48340SMasahiro Yamada $linux_types = 2; 16350a48340SMasahiro Yamada # Warn until headers are all fixed 16450a48340SMasahiro Yamada #$ret = 1; 16550a48340SMasahiro Yamada } 16650a48340SMasahiro Yamada} 167