162306a36Sopenharmony_ci#!/usr/bin/env perl 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ci# headers_check.pl execute a number of trivial consistency checks 562306a36Sopenharmony_ci# 662306a36Sopenharmony_ci# Usage: headers_check.pl dir arch [files...] 762306a36Sopenharmony_ci# dir: dir to look for included files 862306a36Sopenharmony_ci# arch: architecture 962306a36Sopenharmony_ci# files: list of files to check 1062306a36Sopenharmony_ci# 1162306a36Sopenharmony_ci# The script reads the supplied files line by line and: 1262306a36Sopenharmony_ci# 1362306a36Sopenharmony_ci# 1) for each include statement it checks if the 1462306a36Sopenharmony_ci# included file actually exists. 1562306a36Sopenharmony_ci# Only include files located in asm* and linux* are checked. 1662306a36Sopenharmony_ci# The rest are assumed to be system include files. 1762306a36Sopenharmony_ci# 1862306a36Sopenharmony_ci# 2) It is checked that prototypes does not use "extern" 1962306a36Sopenharmony_ci# 2062306a36Sopenharmony_ci# 3) Check for leaked CONFIG_ symbols 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciuse warnings; 2362306a36Sopenharmony_ciuse strict; 2462306a36Sopenharmony_ciuse File::Basename; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cimy ($dir, $arch, @files) = @ARGV; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cimy $ret = 0; 2962306a36Sopenharmony_cimy $line; 3062306a36Sopenharmony_cimy $lineno = 0; 3162306a36Sopenharmony_cimy $filename; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciforeach my $file (@files) { 3462306a36Sopenharmony_ci $filename = $file; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci open(my $fh, '<', $filename) 3762306a36Sopenharmony_ci or die "$filename: $!\n"; 3862306a36Sopenharmony_ci $lineno = 0; 3962306a36Sopenharmony_ci while ($line = <$fh>) { 4062306a36Sopenharmony_ci $lineno++; 4162306a36Sopenharmony_ci &check_include(); 4262306a36Sopenharmony_ci &check_asm_types(); 4362306a36Sopenharmony_ci &check_sizetypes(); 4462306a36Sopenharmony_ci &check_declarations(); 4562306a36Sopenharmony_ci # Dropped for now. Too much noise &check_config(); 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci close $fh; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ciexit $ret; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cisub check_include 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) { 5462306a36Sopenharmony_ci my $inc = $1; 5562306a36Sopenharmony_ci my $found; 5662306a36Sopenharmony_ci $found = stat($dir . "/" . $inc); 5762306a36Sopenharmony_ci if (!$found) { 5862306a36Sopenharmony_ci $inc =~ s#asm/#asm-$arch/#; 5962306a36Sopenharmony_ci $found = stat($dir . "/" . $inc); 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci if (!$found) { 6262306a36Sopenharmony_ci printf STDERR "$filename:$lineno: included file '$inc' is not exported\n"; 6362306a36Sopenharmony_ci $ret = 1; 6462306a36Sopenharmony_ci } 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cisub check_declarations 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci # soundcard.h is what it is 7162306a36Sopenharmony_ci if ($line =~ m/^void seqbuf_dump\(void\);/) { 7262306a36Sopenharmony_ci return; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci # drm headers are being C++ friendly 7562306a36Sopenharmony_ci if ($line =~ m/^extern "C"/) { 7662306a36Sopenharmony_ci return; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) { 7962306a36Sopenharmony_ci printf STDERR "$filename:$lineno: " . 8062306a36Sopenharmony_ci "userspace cannot reference function or " . 8162306a36Sopenharmony_ci "variable defined in the kernel\n"; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cisub check_config 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) { 8862306a36Sopenharmony_ci printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n"; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cimy $linux_asm_types; 9362306a36Sopenharmony_cisub check_asm_types 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 9662306a36Sopenharmony_ci return; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci if ($lineno == 1) { 9962306a36Sopenharmony_ci $linux_asm_types = 0; 10062306a36Sopenharmony_ci } elsif ($linux_asm_types >= 1) { 10162306a36Sopenharmony_ci return; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) { 10462306a36Sopenharmony_ci $linux_asm_types = 1; 10562306a36Sopenharmony_ci printf STDERR "$filename:$lineno: " . 10662306a36Sopenharmony_ci "include of <linux/types.h> is preferred over <asm/types.h>\n" 10762306a36Sopenharmony_ci # Warn until headers are all fixed 10862306a36Sopenharmony_ci #$ret = 1; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cimy $linux_types; 11362306a36Sopenharmony_cimy %import_stack = (); 11462306a36Sopenharmony_cisub check_include_typesh 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci my $path = $_[0]; 11762306a36Sopenharmony_ci my $import_path; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci my $fh; 12062306a36Sopenharmony_ci my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path); 12162306a36Sopenharmony_ci for my $possible ( @file_paths ) { 12262306a36Sopenharmony_ci if (not $import_stack{$possible} and open($fh, '<', $possible)) { 12362306a36Sopenharmony_ci $import_path = $possible; 12462306a36Sopenharmony_ci $import_stack{$import_path} = 1; 12562306a36Sopenharmony_ci last; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci if (eof $fh) { 12962306a36Sopenharmony_ci return; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci my $line; 13362306a36Sopenharmony_ci while ($line = <$fh>) { 13462306a36Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 13562306a36Sopenharmony_ci $linux_types = 1; 13662306a36Sopenharmony_ci last; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 13962306a36Sopenharmony_ci check_include_typesh($included); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci close $fh; 14362306a36Sopenharmony_ci delete $import_stack{$import_path}; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cisub check_sizetypes 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 14962306a36Sopenharmony_ci return; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci if ($lineno == 1) { 15262306a36Sopenharmony_ci $linux_types = 0; 15362306a36Sopenharmony_ci } elsif ($linux_types >= 1) { 15462306a36Sopenharmony_ci return; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 15762306a36Sopenharmony_ci $linux_types = 1; 15862306a36Sopenharmony_ci return; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 16162306a36Sopenharmony_ci check_include_typesh($included); 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci if ($line =~ m/__[us](8|16|32|64)\b/) { 16462306a36Sopenharmony_ci printf STDERR "$filename:$lineno: " . 16562306a36Sopenharmony_ci "found __[us]{8,16,32,64} type " . 16662306a36Sopenharmony_ci "without #include <linux/types.h>\n"; 16762306a36Sopenharmony_ci $linux_types = 2; 16862306a36Sopenharmony_ci # Warn until headers are all fixed 16962306a36Sopenharmony_ci #$ret = 1; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci} 172