18c2ecf20Sopenharmony_ci#!/usr/bin/env perl 28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 38c2ecf20Sopenharmony_ci# 48c2ecf20Sopenharmony_ci# headers_check.pl execute a number of trivial consistency checks 58c2ecf20Sopenharmony_ci# 68c2ecf20Sopenharmony_ci# Usage: headers_check.pl dir arch [files...] 78c2ecf20Sopenharmony_ci# dir: dir to look for included files 88c2ecf20Sopenharmony_ci# arch: architecture 98c2ecf20Sopenharmony_ci# files: list of files to check 108c2ecf20Sopenharmony_ci# 118c2ecf20Sopenharmony_ci# The script reads the supplied files line by line and: 128c2ecf20Sopenharmony_ci# 138c2ecf20Sopenharmony_ci# 1) for each include statement it checks if the 148c2ecf20Sopenharmony_ci# included file actually exists. 158c2ecf20Sopenharmony_ci# Only include files located in asm* and linux* are checked. 168c2ecf20Sopenharmony_ci# The rest are assumed to be system include files. 178c2ecf20Sopenharmony_ci# 188c2ecf20Sopenharmony_ci# 2) It is checked that prototypes does not use "extern" 198c2ecf20Sopenharmony_ci# 208c2ecf20Sopenharmony_ci# 3) Check for leaked CONFIG_ symbols 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciuse warnings; 238c2ecf20Sopenharmony_ciuse strict; 248c2ecf20Sopenharmony_ciuse File::Basename; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cimy ($dir, $arch, @files) = @ARGV; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cimy $ret = 0; 298c2ecf20Sopenharmony_cimy $line; 308c2ecf20Sopenharmony_cimy $lineno = 0; 318c2ecf20Sopenharmony_cimy $filename; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ciforeach my $file (@files) { 348c2ecf20Sopenharmony_ci $filename = $file; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci open(my $fh, '<', $filename) 378c2ecf20Sopenharmony_ci or die "$filename: $!\n"; 388c2ecf20Sopenharmony_ci $lineno = 0; 398c2ecf20Sopenharmony_ci while ($line = <$fh>) { 408c2ecf20Sopenharmony_ci $lineno++; 418c2ecf20Sopenharmony_ci &check_include(); 428c2ecf20Sopenharmony_ci &check_asm_types(); 438c2ecf20Sopenharmony_ci &check_sizetypes(); 448c2ecf20Sopenharmony_ci &check_declarations(); 458c2ecf20Sopenharmony_ci # Dropped for now. Too much noise &check_config(); 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci close $fh; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ciexit $ret; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cisub check_include 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) { 548c2ecf20Sopenharmony_ci my $inc = $1; 558c2ecf20Sopenharmony_ci my $found; 568c2ecf20Sopenharmony_ci $found = stat($dir . "/" . $inc); 578c2ecf20Sopenharmony_ci if (!$found) { 588c2ecf20Sopenharmony_ci $inc =~ s#asm/#asm-$arch/#; 598c2ecf20Sopenharmony_ci $found = stat($dir . "/" . $inc); 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci if (!$found) { 628c2ecf20Sopenharmony_ci printf STDERR "$filename:$lineno: included file '$inc' is not exported\n"; 638c2ecf20Sopenharmony_ci $ret = 1; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cisub check_declarations 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci # soundcard.h is what it is 718c2ecf20Sopenharmony_ci if ($line =~ m/^void seqbuf_dump\(void\);/) { 728c2ecf20Sopenharmony_ci return; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci # drm headers are being C++ friendly 758c2ecf20Sopenharmony_ci if ($line =~ m/^extern "C"/) { 768c2ecf20Sopenharmony_ci return; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) { 798c2ecf20Sopenharmony_ci printf STDERR "$filename:$lineno: " . 808c2ecf20Sopenharmony_ci "userspace cannot reference function or " . 818c2ecf20Sopenharmony_ci "variable defined in the kernel\n"; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cisub check_config 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) { 888c2ecf20Sopenharmony_ci printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n"; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cimy $linux_asm_types; 938c2ecf20Sopenharmony_cisub check_asm_types 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 968c2ecf20Sopenharmony_ci return; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci if ($lineno == 1) { 998c2ecf20Sopenharmony_ci $linux_asm_types = 0; 1008c2ecf20Sopenharmony_ci } elsif ($linux_asm_types >= 1) { 1018c2ecf20Sopenharmony_ci return; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) { 1048c2ecf20Sopenharmony_ci $linux_asm_types = 1; 1058c2ecf20Sopenharmony_ci printf STDERR "$filename:$lineno: " . 1068c2ecf20Sopenharmony_ci "include of <linux/types.h> is preferred over <asm/types.h>\n" 1078c2ecf20Sopenharmony_ci # Warn until headers are all fixed 1088c2ecf20Sopenharmony_ci #$ret = 1; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cimy $linux_types; 1138c2ecf20Sopenharmony_cimy %import_stack = (); 1148c2ecf20Sopenharmony_cisub check_include_typesh 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci my $path = $_[0]; 1178c2ecf20Sopenharmony_ci my $import_path; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci my $fh; 1208c2ecf20Sopenharmony_ci my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path); 1218c2ecf20Sopenharmony_ci for my $possible ( @file_paths ) { 1228c2ecf20Sopenharmony_ci if (not $import_stack{$possible} and open($fh, '<', $possible)) { 1238c2ecf20Sopenharmony_ci $import_path = $possible; 1248c2ecf20Sopenharmony_ci $import_stack{$import_path} = 1; 1258c2ecf20Sopenharmony_ci last; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci if (eof $fh) { 1298c2ecf20Sopenharmony_ci return; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci my $line; 1338c2ecf20Sopenharmony_ci while ($line = <$fh>) { 1348c2ecf20Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 1358c2ecf20Sopenharmony_ci $linux_types = 1; 1368c2ecf20Sopenharmony_ci last; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 1398c2ecf20Sopenharmony_ci check_include_typesh($included); 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci close $fh; 1438c2ecf20Sopenharmony_ci delete $import_stack{$import_path}; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cisub check_sizetypes 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) { 1498c2ecf20Sopenharmony_ci return; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci if ($lineno == 1) { 1528c2ecf20Sopenharmony_ci $linux_types = 0; 1538c2ecf20Sopenharmony_ci } elsif ($linux_types >= 1) { 1548c2ecf20Sopenharmony_ci return; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) { 1578c2ecf20Sopenharmony_ci $linux_types = 1; 1588c2ecf20Sopenharmony_ci return; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) { 1618c2ecf20Sopenharmony_ci check_include_typesh($included); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci if ($line =~ m/__[us](8|16|32|64)\b/) { 1648c2ecf20Sopenharmony_ci printf STDERR "$filename:$lineno: " . 1658c2ecf20Sopenharmony_ci "found __[us]{8,16,32,64} type " . 1668c2ecf20Sopenharmony_ci "without #include <linux/types.h>\n"; 1678c2ecf20Sopenharmony_ci $linux_types = 2; 1688c2ecf20Sopenharmony_ci # Warn until headers are all fixed 1698c2ecf20Sopenharmony_ci #$ret = 1; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci} 172