headers_check.pl 3.6 KB
Newer Older
1
#!/usr/bin/perl -w
2 3 4
#
# headers_check.pl execute a number of trivial consistency checks
#
5
# Usage: headers_check.pl dir arch [files...]
6 7 8 9 10 11 12 13 14 15 16
# 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.
#
17 18
# 2) It is checked that prototypes does not use "extern"
#
19
# 3) Check for leaked CONFIG_ symbols
20 21

use strict;
22
use File::Basename;
23 24 25 26 27 28 29 30 31 32

my ($dir, $arch, @files) = @ARGV;

my $ret = 0;
my $line;
my $lineno = 0;
my $filename;

foreach my $file (@files) {
	$filename = $file;
33 34 35

	open(my $fh, '<', $filename)
		or die "$filename: $!\n";
36
	$lineno = 0;
37
	while ($line = <$fh>) {
38
		$lineno++;
39 40 41
		&check_include();
		&check_asm_types();
		&check_sizetypes();
42
		&check_declarations();
43
		# Dropped for now. Too much noise &check_config();
44
	}
45
	close $fh;
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
}
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;
		}
	}
}
65

66
sub check_declarations
67
{
68 69 70 71 72
	# soundcard.h is what it is
	if ($line =~ m/^void seqbuf_dump\(void\);/) {
		return;
	}
	if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) {
73
		printf STDERR "$filename:$lineno: " .
74 75
			      "userspace cannot reference function or " .
			      "variable defined in the kernel\n";
76 77
	}
}
78 79 80

sub check_config
{
81
	if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) {
82 83 84 85
		printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n";
	}
}

86
my $linux_asm_types;
87
sub check_asm_types
88
{
89 90 91
	if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
		return;
	}
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	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;
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
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};
}

140 141
sub check_sizetypes
{
142 143 144
	if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
		return;
	}
145 146 147 148 149 150 151 152 153
	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;
	}
154 155 156
	if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
		check_include_typesh($included);
	}
157 158 159 160 161 162 163 164 165
	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;
	}
}