Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[linux-2.6] / scripts / reference_init.pl
1 #!/usr/bin/perl -w
2 #
3 # reference_init.pl (C) Keith Owens 2002 <kaos@ocs.com.au>
4 #
5 # List references to vmlinux init sections from non-init sections.
6
7 # Unfortunately I had to exclude references from read only data to .init
8 # sections, almost all of these are false positives, they are created by
9 # gcc.  The downside of excluding rodata is that there really are some
10 # user references from rodata to init code, e.g. drivers/video/vgacon.c
11 #
12 # const struct consw vga_con = {
13 #        con_startup:            vgacon_startup,
14 #
15 # where vgacon_startup is __init.  If you want to wade through the false
16 # positives, take out the check for rodata.
17
18 use strict;
19 die($0 . " takes no arguments\n") if($#ARGV >= 0);
20
21 my %object;
22 my $object;
23 my $line;
24 my $ignore;
25
26 $| = 1;
27
28 printf("Finding objects, ");
29 open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed";
30 while (defined($line = <OBJDUMP_LIST>)) {
31         chomp($line);
32         if ($line =~ /:\s+file format/) {
33                 ($object = $line) =~ s/:.*//;
34                 $object{$object}->{'module'} = 0;
35                 $object{$object}->{'size'} = 0;
36                 $object{$object}->{'off'} = 0;
37         }
38         if ($line =~ /^\s*\d+\s+\.modinfo\s+/) {
39                 $object{$object}->{'module'} = 1;
40         }
41         if ($line =~ /^\s*\d+\s+\.comment\s+/) {
42                 ($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5];
43         }
44 }
45 close(OBJDUMP_LIST);
46 printf("%d objects, ", scalar keys(%object));
47 $ignore = 0;
48 foreach $object (keys(%object)) {
49         if ($object{$object}->{'module'}) {
50                 ++$ignore;
51                 delete($object{$object});
52         }
53 }
54 printf("ignoring %d module(s)\n", $ignore);
55
56 # Ignore conglomerate objects, they have been built from multiple objects and we
57 # only care about the individual objects.  If an object has more than one GCC:
58 # string in the comment section then it is conglomerate.  This does not filter
59 # out conglomerates that consist of exactly one object, can't be helped.
60
61 printf("Finding conglomerates, ");
62 $ignore = 0;
63 foreach $object (keys(%object)) {
64         if (exists($object{$object}->{'off'})) {
65                 my ($off, $size, $comment, $l);
66                 $off = hex($object{$object}->{'off'});
67                 $size = hex($object{$object}->{'size'});
68                 open(OBJECT, "<$object") || die "cannot read $object";
69                 seek(OBJECT, $off, 0) || die "seek to $off in $object failed";
70                 $l = read(OBJECT, $comment, $size);
71                 die "read $size bytes from $object .comment failed" if ($l != $size);
72                 close(OBJECT);
73                 if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) {
74                         ++$ignore;
75                         delete($object{$object});
76                 }
77         }
78 }
79 printf("ignoring %d conglomerate(s)\n", $ignore);
80
81 printf("Scanning objects\n");
82 foreach $object (sort(keys(%object))) {
83         my $from;
84         open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object";
85         while (defined($line = <OBJDUMP>)) {
86                 chomp($line);
87                 if ($line =~ /RELOCATION RECORDS FOR /) {
88                         ($from = $line) =~ s/.*\[([^]]*).*/$1/;
89                 }
90                 if (($line =~ /\.init$/ || $line =~ /\.init\./) &&
91                     ($from !~ /\.init$/ &&
92                      $from !~ /\.init\./ &&
93                      $from !~ /\.stab$/ &&
94                      $from !~ /\.rodata$/ &&
95                      $from !~ /\.text\.lock$/ &&
96                      $from !~ /\.pci_fixup_header$/ &&
97                      $from !~ /\.pci_fixup_final$/ &&
98                      $from !~ /\.pdr$/ &&
99                      $from !~ /\__param$/ &&
100                      $from !~ /\.altinstructions/ &&
101                      $from !~ /\.eh_frame/ &&
102                      $from !~ /\.debug_/)) {
103                         printf("Error: %s %s refers to %s\n", $object, $from, $line);
104                 }
105         }
106         close(OBJDUMP);
107 }
108 printf("Done\n");