xref: /linux-6.15/usr/include/headers_check.pl (revision d67393f4)
150a48340SMasahiro Yamada#!/usr/bin/env perl
250a48340SMasahiro Yamada# SPDX-License-Identifier: GPL-2.0
350a48340SMasahiro Yamada#
450a48340SMasahiro Yamada# headers_check.pl execute a number of trivial consistency checks
550a48340SMasahiro Yamada#
6*d67393f4SGeert Uytterhoeven# Usage: headers_check.pl dir [files...]
750a48340SMasahiro Yamada# dir:   dir to look for included files
850a48340SMasahiro Yamada# files: list of files to check
950a48340SMasahiro Yamada#
1050a48340SMasahiro Yamada# The script reads the supplied files line by line and:
1150a48340SMasahiro Yamada#
1250a48340SMasahiro Yamada# 1) for each include statement it checks if the
1350a48340SMasahiro Yamada#    included file actually exists.
1450a48340SMasahiro Yamada#    Only include files located in asm* and linux* are checked.
1550a48340SMasahiro Yamada#    The rest are assumed to be system include files.
1650a48340SMasahiro Yamada#
1750a48340SMasahiro Yamada# 2) It is checked that prototypes does not use "extern"
1850a48340SMasahiro Yamada#
1950a48340SMasahiro Yamada# 3) Check for leaked CONFIG_ symbols
2050a48340SMasahiro Yamada
2150a48340SMasahiro Yamadause warnings;
2250a48340SMasahiro Yamadause strict;
2350a48340SMasahiro Yamadause File::Basename;
2450a48340SMasahiro Yamada
25*d67393f4SGeert Uytterhoevenmy ($dir, @files) = @ARGV;
2650a48340SMasahiro Yamada
2750a48340SMasahiro Yamadamy $ret = 0;
2850a48340SMasahiro Yamadamy $line;
2950a48340SMasahiro Yamadamy $lineno = 0;
3050a48340SMasahiro Yamadamy $filename;
3150a48340SMasahiro Yamada
3250a48340SMasahiro Yamadaforeach my $file (@files) {
3350a48340SMasahiro Yamada	$filename = $file;
3450a48340SMasahiro Yamada
3550a48340SMasahiro Yamada	open(my $fh, '<', $filename)
3650a48340SMasahiro Yamada		or die "$filename: $!\n";
3750a48340SMasahiro Yamada	$lineno = 0;
3850a48340SMasahiro Yamada	while ($line = <$fh>) {
3950a48340SMasahiro Yamada		$lineno++;
4050a48340SMasahiro Yamada		&check_include();
4150a48340SMasahiro Yamada		&check_asm_types();
4250a48340SMasahiro Yamada		&check_sizetypes();
4350a48340SMasahiro Yamada		&check_declarations();
4450a48340SMasahiro Yamada		# Dropped for now. Too much noise &check_config();
4550a48340SMasahiro Yamada	}
4650a48340SMasahiro Yamada	close $fh;
4750a48340SMasahiro Yamada}
4850a48340SMasahiro Yamadaexit $ret;
4950a48340SMasahiro Yamada
5050a48340SMasahiro Yamadasub check_include
5150a48340SMasahiro Yamada{
5250a48340SMasahiro Yamada	if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) {
5350a48340SMasahiro Yamada		my $inc = $1;
5450a48340SMasahiro Yamada		my $found;
5550a48340SMasahiro Yamada		$found = stat($dir . "/" . $inc);
5650a48340SMasahiro Yamada		if (!$found) {
5750a48340SMasahiro Yamada			printf STDERR "$filename:$lineno: included file '$inc' is not exported\n";
5850a48340SMasahiro Yamada			$ret = 1;
5950a48340SMasahiro Yamada		}
6050a48340SMasahiro Yamada	}
6150a48340SMasahiro Yamada}
6250a48340SMasahiro Yamada
6350a48340SMasahiro Yamadasub check_declarations
6450a48340SMasahiro Yamada{
6550a48340SMasahiro Yamada	# soundcard.h is what it is
6650a48340SMasahiro Yamada	if ($line =~ m/^void seqbuf_dump\(void\);/) {
6750a48340SMasahiro Yamada		return;
6850a48340SMasahiro Yamada	}
6950a48340SMasahiro Yamada	# drm headers are being C++ friendly
7050a48340SMasahiro Yamada	if ($line =~ m/^extern "C"/) {
7150a48340SMasahiro Yamada		return;
7250a48340SMasahiro Yamada	}
7350a48340SMasahiro Yamada	if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) {
7450a48340SMasahiro Yamada		printf STDERR "$filename:$lineno: " .
7550a48340SMasahiro Yamada			      "userspace cannot reference function or " .
7650a48340SMasahiro Yamada			      "variable defined in the kernel\n";
7750a48340SMasahiro Yamada	}
7850a48340SMasahiro Yamada}
7950a48340SMasahiro Yamada
8050a48340SMasahiro Yamadasub check_config
8150a48340SMasahiro Yamada{
8250a48340SMasahiro Yamada	if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) {
8350a48340SMasahiro Yamada		printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n";
8450a48340SMasahiro Yamada	}
8550a48340SMasahiro Yamada}
8650a48340SMasahiro Yamada
8750a48340SMasahiro Yamadamy $linux_asm_types;
8850a48340SMasahiro Yamadasub check_asm_types
8950a48340SMasahiro Yamada{
9050a48340SMasahiro Yamada	if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
9150a48340SMasahiro Yamada		return;
9250a48340SMasahiro Yamada	}
9350a48340SMasahiro Yamada	if ($lineno == 1) {
9450a48340SMasahiro Yamada		$linux_asm_types = 0;
9550a48340SMasahiro Yamada	} elsif ($linux_asm_types >= 1) {
9650a48340SMasahiro Yamada		return;
9750a48340SMasahiro Yamada	}
9850a48340SMasahiro Yamada	if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) {
9950a48340SMasahiro Yamada		$linux_asm_types = 1;
10050a48340SMasahiro Yamada		printf STDERR "$filename:$lineno: " .
10150a48340SMasahiro Yamada		"include of <linux/types.h> is preferred over <asm/types.h>\n"
10250a48340SMasahiro Yamada		# Warn until headers are all fixed
10350a48340SMasahiro Yamada		#$ret = 1;
10450a48340SMasahiro Yamada	}
10550a48340SMasahiro Yamada}
10650a48340SMasahiro Yamada
10750a48340SMasahiro Yamadamy $linux_types;
10850a48340SMasahiro Yamadamy %import_stack = ();
10950a48340SMasahiro Yamadasub check_include_typesh
11050a48340SMasahiro Yamada{
11150a48340SMasahiro Yamada	my $path = $_[0];
11250a48340SMasahiro Yamada	my $import_path;
11350a48340SMasahiro Yamada
11450a48340SMasahiro Yamada	my $fh;
11550a48340SMasahiro Yamada	my @file_paths = ($path, $dir . "/" .  $path, dirname($filename) . "/" . $path);
11650a48340SMasahiro Yamada	for my $possible ( @file_paths ) {
11750a48340SMasahiro Yamada	    if (not $import_stack{$possible} and open($fh, '<', $possible)) {
11850a48340SMasahiro Yamada		$import_path = $possible;
11950a48340SMasahiro Yamada		$import_stack{$import_path} = 1;
12050a48340SMasahiro Yamada		last;
12150a48340SMasahiro Yamada	    }
12250a48340SMasahiro Yamada	}
12350a48340SMasahiro Yamada	if (eof $fh) {
12450a48340SMasahiro Yamada	    return;
12550a48340SMasahiro Yamada	}
12650a48340SMasahiro Yamada
12750a48340SMasahiro Yamada	my $line;
12850a48340SMasahiro Yamada	while ($line = <$fh>) {
12950a48340SMasahiro Yamada		if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
13050a48340SMasahiro Yamada			$linux_types = 1;
13150a48340SMasahiro Yamada			last;
13250a48340SMasahiro Yamada		}
13350a48340SMasahiro Yamada		if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
13450a48340SMasahiro Yamada			check_include_typesh($included);
13550a48340SMasahiro Yamada		}
13650a48340SMasahiro Yamada	}
13750a48340SMasahiro Yamada	close $fh;
13850a48340SMasahiro Yamada	delete $import_stack{$import_path};
13950a48340SMasahiro Yamada}
14050a48340SMasahiro Yamada
14150a48340SMasahiro Yamadasub check_sizetypes
14250a48340SMasahiro Yamada{
14350a48340SMasahiro Yamada	if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
14450a48340SMasahiro Yamada		return;
14550a48340SMasahiro Yamada	}
14650a48340SMasahiro Yamada	if ($lineno == 1) {
14750a48340SMasahiro Yamada		$linux_types = 0;
14850a48340SMasahiro Yamada	} elsif ($linux_types >= 1) {
14950a48340SMasahiro Yamada		return;
15050a48340SMasahiro Yamada	}
15150a48340SMasahiro Yamada	if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
15250a48340SMasahiro Yamada		$linux_types = 1;
15350a48340SMasahiro Yamada		return;
15450a48340SMasahiro Yamada	}
15550a48340SMasahiro Yamada	if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
15650a48340SMasahiro Yamada		check_include_typesh($included);
15750a48340SMasahiro Yamada	}
15850a48340SMasahiro Yamada	if ($line =~ m/__[us](8|16|32|64)\b/) {
15950a48340SMasahiro Yamada		printf STDERR "$filename:$lineno: " .
16050a48340SMasahiro Yamada		              "found __[us]{8,16,32,64} type " .
16150a48340SMasahiro Yamada		              "without #include <linux/types.h>\n";
16250a48340SMasahiro Yamada		$linux_types = 2;
16350a48340SMasahiro Yamada		# Warn until headers are all fixed
16450a48340SMasahiro Yamada		#$ret = 1;
16550a48340SMasahiro Yamada	}
16650a48340SMasahiro Yamada}
167