headers_check.pl 3.51 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
	if ($line =~m/^(\s*extern|unsigned|char|short|int|long|void)\b/) {
69
		printf STDERR "$filename:$lineno: " .
70
71
			      "userspace cannot reference function or " .
			      "variable defined in the kernel\n";
72
73
	}
}
74
75
76

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

82
my $linux_asm_types;
83
sub check_asm_types
84
{
85
86
87
	if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
		return;
	}
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
	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;
103
104
105
106
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
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};
}

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