]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/tool/checkinitcalls
update
[l4.git] / kernel / fiasco / tool / checkinitcalls
1 #!/usr/bin/perl -w
2
3 # we use BigInts for handling 64-bit values on IA32 systems
4
5 use strict;
6 use Getopt::Long;
7 use Pod::Usage;
8 use Math::BigInt;
9
10 my $target       = '';
11 my $sym_objdump  = 'nm -nC';
12 my $dis_objdump  = 'objdump -drlC';
13 my $hdr_objdump  = 'objdump -h';
14 my $start_symbol = '_initcall_start';
15 my $end_symbol   = '_initcall_end';
16 my $kernel       = 'fiasco.image';
17 my $error        = 0;
18 my $werror       = 0;
19 my @Wswitch      = ();
20 my @ignore_funcs = ();
21
22 my $opt = { "kernel"          => \$kernel,
23             "start-symbol"    => \$start_symbol,
24             "end-symbol"      => \$end_symbol,
25             "W"               => \@Wswitch,
26             "ignore-function" => \@ignore_funcs,
27             "target"          => \$target };
28
29 Getopt::Long::Configure ('bundling','no_ignore_case','auto_abbrev');
30
31 GetOptions( $opt,
32             "help|?|h",
33             "man|m",
34             "W=s@",
35             "start-symbol=s",
36             "end-symbol=s",
37             "ignore-function=s@",
38             "kernel|k=s",
39             "target|t=s",
40           );
41
42 sub have_warn_opt {
43   my $opt = shift @_;
44   my @gr = grep /$opt/, @Wswitch;
45 #  print "W: ".join(" ",@gr)."\n";
46   return scalar @gr;
47 }
48
49 $dis_objdump = $target.$dis_objdump;
50 $hdr_objdump = $target.$hdr_objdump;
51 $sym_objdump = $target.$sym_objdump;
52
53 $werror = 1 if have_warn_opt("error");
54 if (!have_warn_opt("static-construction")) {
55   push @ignore_funcs, ("(_Z41)?__static_initialization_and_destruction_0(ii\\.(clone|part)\\.\\d+)?");
56   push @ignore_funcs, ("_GLOBAL__(sub_)?I\\.\\S*");
57   push @ignore_funcs, ("_GLOBAL__sub_I__Z\\S*");
58   push @ignore_funcs, ("global constructors keyed to \\S*");
59   push @ignore_funcs, ("T\\.\\d+");
60 }
61
62 my $ignore_funcs = join("|",@ignore_funcs);
63
64 #print "Ignore: $ignore_funcs\n";
65
66 my @symbols = split($/,qx{$sym_objdump $kernel});
67
68 my @start = grep /^[0-9a-fA-F]+\s+[A-Z]\s+$start_symbol\s*$/, @symbols;
69 my @end   = grep /^[0-9a-fA-F]+\s+[A-Z]\s+$end_symbol\s*$/, @symbols;
70
71 if(! defined $start[0] || ! defined $end[0]) {
72   die 'start ('.$start_symbol.') or end ('.$end_symbol.') symbol not found!';
73 }
74
75 my $start = $start[0];
76 my $end   = $end[0];
77
78 $start =~ s/^([0-9a-fA-F]+).*$/$1/;
79 $end   =~ s/^([0-9a-fA-F]+).*$/$1/;
80
81 #print "start of init area: $start\n";
82 #print "end if init area  : $end\n";
83
84 $start = Math::BigInt->new("0x".$start);
85 $end   = Math::BigInt->new("0x".$end);
86
87 my %init_syms;
88
89 while($_ = shift @symbols) {
90   if(/^([0-9a-fA-F]+)\s+[A-Z]\s+(\S+)/) {
91     my $addr   = Math::BigInt->new("0x".$1);
92     my $symbol = $2;
93     if (   $symbol ne $start_symbol
94         && $symbol ne $end_symbol
95         && $addr->bcmp($start) >= 0
96         && $addr->bcmp($end)   <  0) {
97       $init_syms{$symbol} = 1;
98 #      print "$symbol\n";
99     }
100   }
101 }
102
103 while($_ = shift @ARGV) {
104   my $file = $_;
105
106   # search for sections .text.* in object file
107   my @sections = split $/, qx{$hdr_objdump $file};
108   my $text_sections = '';
109   foreach $_ (@sections) {
110     if (/^\s*[0-9]+\s(\.text[.0-9a-zA-Z_]*)/) {
111       $text_sections .= " -j ".$1;
112     }
113   }
114
115   # disassemble object file
116   my @dump = split $/, qx{$dis_objdump $text_sections $file};
117
118   my $source;
119   my $function;
120   my $warn;
121   if ($werror) {
122     $warn = "error";
123   } else {
124     $warn = "warning";
125   }
126
127   foreach $_ (@dump) {
128     if (/^(\S+:[0-9]+)\s*$/) {
129       $source = $1;
130       next;
131     }
132     if (/^([0-9a-fA-F]+)\s+<(.*)>:$/) {
133       $function = $2;
134       next;
135     }
136     if (/^\s*([0-9a-fA-F]+):\s+R_\S+\s+(\S+\(.*\))\S*\s*$/) {
137       my $sym = $2;
138       if (   defined $function
139           && $function !~ /^($ignore_funcs)(\(.*\))?$/
140           && defined $init_syms{$sym}) {
141         $source = $file unless defined $source;
142         (my $func_pretty = $function) =~ s/_GLOBAL__I\.\d+_//;
143         $func_pretty = `echo '$func_pretty' | ${target}c++filt`;
144         chomp $func_pretty;
145         print STDERR "$source: $warn: $func_pretty uses initcall ($sym) from normal text section\n";
146         $error++ if $werror;
147       }
148       next;
149     }
150   }
151 }
152
153 exit(1) if $error;