headers_check.pl 3.7 KB

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