headers_check.pl 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/env perl
  2. # SPDX-License-Identifier: GPL-2.0
  3. #
  4. # headers_check.pl execute a number of trivial consistency checks
  5. #
  6. # Usage: headers_check.pl dir arch [files...]
  7. # dir: dir to look for included files
  8. # arch: architecture
  9. # files: list of files to check
  10. #
  11. # The script reads the supplied files line by line and:
  12. #
  13. # 1) for each include statement it checks if the
  14. # included file actually exists.
  15. # Only include files located in asm* and linux* are checked.
  16. # The rest are assumed to be system include files.
  17. #
  18. # 2) It is checked that prototypes does not use "extern"
  19. #
  20. # 3) Check for leaked CONFIG_ symbols
  21. use warnings;
  22. use strict;
  23. use File::Basename;
  24. my ($dir, $arch, @files) = @ARGV;
  25. my $ret = 0;
  26. my $line;
  27. my $lineno = 0;
  28. my $filename;
  29. foreach my $file (@files) {
  30. $filename = $file;
  31. open(my $fh, '<', $filename)
  32. or die "$filename: $!\n";
  33. $lineno = 0;
  34. while ($line = <$fh>) {
  35. $lineno++;
  36. &check_include();
  37. &check_asm_types();
  38. &check_sizetypes();
  39. &check_declarations();
  40. # Dropped for now. Too much noise &check_config();
  41. }
  42. close $fh;
  43. }
  44. exit $ret;
  45. sub check_include
  46. {
  47. if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) {
  48. my $inc = $1;
  49. my $found;
  50. $found = stat($dir . "/" . $inc);
  51. if (!$found) {
  52. $inc =~ s#asm/#asm-$arch/#;
  53. $found = stat($dir . "/" . $inc);
  54. }
  55. if (!$found) {
  56. printf STDERR "$filename:$lineno: included file '$inc' is not exported\n";
  57. $ret = 1;
  58. }
  59. }
  60. }
  61. sub check_declarations
  62. {
  63. # soundcard.h is what it is
  64. if ($line =~ m/^void seqbuf_dump\(void\);/) {
  65. return;
  66. }
  67. # drm headers are being C++ friendly
  68. if ($line =~ m/^extern "C"/) {
  69. return;
  70. }
  71. if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) {
  72. printf STDERR "$filename:$lineno: " .
  73. "userspace cannot reference function or " .
  74. "variable defined in the kernel\n";
  75. }
  76. }
  77. sub check_config
  78. {
  79. if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) {
  80. printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n";
  81. }
  82. }
  83. my $linux_asm_types;
  84. sub check_asm_types
  85. {
  86. if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
  87. return;
  88. }
  89. if ($lineno == 1) {
  90. $linux_asm_types = 0;
  91. } elsif ($linux_asm_types >= 1) {
  92. return;
  93. }
  94. if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) {
  95. $linux_asm_types = 1;
  96. printf STDERR "$filename:$lineno: " .
  97. "include of <linux/types.h> is preferred over <asm/types.h>\n"
  98. # Warn until headers are all fixed
  99. #$ret = 1;
  100. }
  101. }
  102. my $linux_types;
  103. my %import_stack = ();
  104. sub check_include_typesh
  105. {
  106. my $path = $_[0];
  107. my $import_path;
  108. my $fh;
  109. my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path);
  110. for my $possible ( @file_paths ) {
  111. if (not $import_stack{$possible} and open($fh, '<', $possible)) {
  112. $import_path = $possible;
  113. $import_stack{$import_path} = 1;
  114. last;
  115. }
  116. }
  117. if (eof $fh) {
  118. return;
  119. }
  120. my $line;
  121. while ($line = <$fh>) {
  122. if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
  123. $linux_types = 1;
  124. last;
  125. }
  126. if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
  127. check_include_typesh($included);
  128. }
  129. }
  130. close $fh;
  131. delete $import_stack{$import_path};
  132. }
  133. sub check_sizetypes
  134. {
  135. if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
  136. return;
  137. }
  138. if ($lineno == 1) {
  139. $linux_types = 0;
  140. } elsif ($linux_types >= 1) {
  141. return;
  142. }
  143. if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
  144. $linux_types = 1;
  145. return;
  146. }
  147. if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
  148. check_include_typesh($included);
  149. }
  150. if ($line =~ m/__[us](8|16|32|64)\b/) {
  151. printf STDERR "$filename:$lineno: " .
  152. "found __[us]{8,16,32,64} type " .
  153. "without #include <linux/types.h>\n";
  154. $linux_types = 2;
  155. # Warn until headers are all fixed
  156. #$ret = 1;
  157. }
  158. }