2008-10-30 00:20:13 +03:00
#!/usr/bin/perl -w
2008-06-15 23:41:09 +04:00
#
# headers_check.pl execute a number of trivial consistency checks
#
2009-06-05 06:12:01 +04:00
# Usage: headers_check.pl dir arch [files...]
2008-06-15 23:41:09 +04:00
# dir: dir to look for included files
# arch: architecture
# files: list of files to check
#
# The script reads the supplied files line by line and:
#
# 1) for each include statement it checks if the
# included file actually exists.
# Only include files located in asm* and linux* are checked.
# The rest are assumed to be system include files.
#
2008-12-27 10:43:36 +03:00
# 2) It is checked that prototypes does not use "extern"
#
2008-12-27 21:52:20 +03:00
# 3) Check for leaked CONFIG_ symbols
2008-06-15 23:41:09 +04:00
use strict ;
2012-03-06 03:08:09 +04:00
use File::Basename ;
2008-06-15 23:41:09 +04:00
my ( $ dir , $ arch , @ files ) = @ ARGV ;
my $ ret = 0 ;
my $ line ;
my $ lineno = 0 ;
my $ filename ;
foreach my $ file ( @ files ) {
$ filename = $ file ;
2010-02-23 02:17:24 +03:00
open ( my $ fh , '<' , $ filename )
or die "$filename: $!\n" ;
2008-06-15 23:41:09 +04:00
$ lineno = 0 ;
2010-02-23 02:17:24 +03:00
while ( $ line = <$fh> ) {
2008-06-15 23:41:09 +04:00
$ lineno + + ;
2008-12-30 13:34:58 +03:00
& check_include ( ) ;
& check_asm_types ( ) ;
& check_sizetypes ( ) ;
2009-06-05 06:12:01 +04:00
& check_declarations ( ) ;
2009-01-31 01:56:42 +03:00
# Dropped for now. Too much noise &check_config();
2008-06-15 23:41:09 +04:00
}
2010-02-23 02:17:24 +03:00
close $ fh ;
2008-06-15 23:41:09 +04:00
}
exit $ ret ;
sub check_include
{
if ( $ line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/ ) {
my $ inc = $ 1 ;
my $ found ;
$ found = stat ( $ dir . "/" . $ inc ) ;
if ( ! $ found ) {
$ inc =~ s #asm/#asm-$arch/#;
$ found = stat ( $ dir . "/" . $ inc ) ;
}
if ( ! $ found ) {
printf STDERR "$filename:$lineno: included file '$inc' is not exported\n" ;
$ ret = 1 ;
}
}
}
2008-12-27 10:43:36 +03:00
2009-06-05 06:12:01 +04:00
sub check_declarations
2008-12-27 10:43:36 +03:00
{
2010-12-01 00:51:13 +03:00
if ( $ line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/ ) {
2009-06-05 06:12:01 +04:00
printf STDERR "$filename:$lineno: " .
2010-12-01 00:52:14 +03:00
"userspace cannot reference function or " .
"variable defined in the kernel\n" ;
2008-12-27 10:43:36 +03:00
}
}
2008-12-27 21:52:20 +03:00
sub check_config
{
2009-05-13 00:43:36 +04:00
if ( $ line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/ ) {
2008-12-27 21:52:20 +03:00
printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n" ;
}
}
2008-12-30 13:34:58 +03:00
my $ linux_asm_types ;
2010-02-23 02:17:24 +03:00
sub check_asm_types
2008-12-30 13:34:58 +03:00
{
2008-12-31 11:32:30 +03:00
if ( $ filename =~ /types.h|int-l64.h|int-ll64.h/o ) {
return ;
}
2008-12-30 13:34:58 +03:00
if ( $ lineno == 1 ) {
$ linux_asm_types = 0 ;
} elsif ( $ linux_asm_types >= 1 ) {
return ;
}
if ( $ line =~ m/^\s*#\s*include\s+<asm\/types.h>/ ) {
$ linux_asm_types = 1 ;
printf STDERR "$filename:$lineno: " .
"include of <linux/types.h> is preferred over <asm/types.h>\n"
# Warn until headers are all fixed
#$ret = 1;
}
}
my $ linux_types ;
2012-03-06 03:08:09 +04:00
my % import_stack = ( ) ;
sub check_include_typesh
{
my $ path = $ _ [ 0 ] ;
my $ import_path ;
my $ fh ;
my @ file_paths = ( $ path , $ dir . "/" . $ path , dirname ( $ filename ) . "/" . $ path ) ;
for my $ possible ( @ file_paths ) {
if ( not $ import_stack { $ possible } and open ( $ fh , '<' , $ possible ) ) {
$ import_path = $ possible ;
$ import_stack { $ import_path } = 1 ;
last ;
}
}
if ( eof $ fh ) {
return ;
}
my $ line ;
while ( $ line = <$fh> ) {
if ( $ line =~ m/^\s*#\s*include\s+<linux\/types.h>/ ) {
$ linux_types = 1 ;
last ;
}
if ( my $ included = ( $ line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/ ) [ 0 ] ) {
check_include_typesh ( $ included ) ;
}
}
close $ fh ;
delete $ import_stack { $ import_path } ;
}
2008-12-30 13:34:58 +03:00
sub check_sizetypes
{
2008-12-31 11:32:30 +03:00
if ( $ filename =~ /types.h|int-l64.h|int-ll64.h/o ) {
return ;
}
2008-12-30 13:34:58 +03:00
if ( $ lineno == 1 ) {
$ linux_types = 0 ;
} elsif ( $ linux_types >= 1 ) {
return ;
}
if ( $ line =~ m/^\s*#\s*include\s+<linux\/types.h>/ ) {
$ linux_types = 1 ;
return ;
}
2012-03-06 03:08:09 +04:00
if ( my $ included = ( $ line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/ ) [ 0 ] ) {
check_include_typesh ( $ included ) ;
}
2008-12-30 13:34:58 +03:00
if ( $ line =~ m/__[us](8|16|32|64)\b/ ) {
printf STDERR "$filename:$lineno: " .
"found __[us]{8,16,32,64} type " .
"without #include <linux/types.h>\n" ;
$ linux_types = 2 ;
# Warn until headers are all fixed
#$ret = 1;
}
}