Files
foc/kernel/fiasco/tool/checkinitcalls
Stefan Kalkowski fd282ca10c FOC Uptream Github sources (2018-06-25)
Refers to HEAD commit b9145d3ec4ffe3b02b3d49475ff3391905f0b51f
2018-06-25 16:04:22 +02:00

155 lines
3.8 KiB
Perl
Executable File

#!/usr/bin/perl -w
# we use BigInts for handling 64-bit values on IA32 systems
use strict;
use Getopt::Long;
use Pod::Usage;
use Math::BigInt;
my $target = '';
my $sym_objdump = 'nm -nC';
my $dis_objdump = 'objdump -drlC';
my $hdr_objdump = 'objdump -h';
my $start_symbol = '_initcall_start';
my $end_symbol = '_initcall_end';
my $kernel = 'fiasco.image';
my $error = 0;
my $werror = 0;
my @Wswitch = ();
my @ignore_funcs = ();
my $opt = { "kernel" => \$kernel,
"start-symbol" => \$start_symbol,
"end-symbol" => \$end_symbol,
"W" => \@Wswitch,
"ignore-function" => \@ignore_funcs,
"target" => \$target };
Getopt::Long::Configure ('bundling','no_ignore_case','auto_abbrev');
GetOptions( $opt,
"help|?|h",
"man|m",
"W=s@",
"start-symbol=s",
"end-symbol=s",
"ignore-function=s@",
"kernel|k=s",
"target|t=s",
);
sub have_warn_opt {
my $opt = shift @_;
my @gr = grep /$opt/, @Wswitch;
# print "W: ".join(" ",@gr)."\n";
return scalar @gr;
}
$dis_objdump = $target.$dis_objdump;
$hdr_objdump = $target.$hdr_objdump;
$sym_objdump = $target.$sym_objdump;
$werror = 1 if have_warn_opt("error");
if (!have_warn_opt("static-construction")) {
push @ignore_funcs, ("(_Z41)?__static_initialization_and_destruction_0(ii\\.(clone|part)\\.\\d+)?");
push @ignore_funcs, ("__static_initialization_and_destruction_0\\(int, int\\) \\[clone \\.part\\.\\d+\\]");
push @ignore_funcs, ("_GLOBAL__(sub_)?I\\.\\S*");
push @ignore_funcs, ("_GLOBAL__sub_I__Z\\S*");
push @ignore_funcs, ("global constructors keyed to \\S*");
push @ignore_funcs, ("T\\.\\d+");
}
my $ignore_funcs = join("|",@ignore_funcs);
#print "Ignore: $ignore_funcs\n";
my @symbols = split($/,qx{$sym_objdump $kernel});
my @start = grep /^[0-9a-fA-F]+\s+[A-Z]\s+$start_symbol\s*$/, @symbols;
my @end = grep /^[0-9a-fA-F]+\s+[A-Z]\s+$end_symbol\s*$/, @symbols;
if(! defined $start[0] || ! defined $end[0]) {
die 'start ('.$start_symbol.') or end ('.$end_symbol.') symbol not found!';
}
my $start = $start[0];
my $end = $end[0];
$start =~ s/^([0-9a-fA-F]+).*$/$1/;
$end =~ s/^([0-9a-fA-F]+).*$/$1/;
#print "start of init area: $start\n";
#print "end if init area : $end\n";
$start = Math::BigInt->new("0x".$start);
$end = Math::BigInt->new("0x".$end);
my %init_syms;
while($_ = shift @symbols) {
if(/^([0-9a-fA-F]+)\s+[A-Z]\s+(\S+)/) {
my $addr = Math::BigInt->new("0x".$1);
my $symbol = $2;
if ( $symbol ne $start_symbol
&& $symbol ne $end_symbol
&& $addr->bcmp($start) >= 0
&& $addr->bcmp($end) < 0) {
$init_syms{$symbol} = 1;
# print "$symbol\n";
}
}
}
while($_ = shift @ARGV) {
my $file = $_;
# search for sections .text.* in object file
my @sections = split $/, qx{$hdr_objdump $file};
my $text_sections = '';
foreach $_ (@sections) {
if (/^\s*[0-9]+\s(\.text[.0-9a-zA-Z_]*)/) {
$text_sections .= " -j ".$1;
}
}
# disassemble object file
my @dump = split $/, qx{$dis_objdump $text_sections $file};
my $source;
my $function;
my $warn;
if ($werror) {
$warn = "error";
} else {
$warn = "warning";
}
foreach $_ (@dump) {
if (/^(\S+:[0-9]+)\s*$/) {
$source = $1;
next;
}
if (/^([0-9a-fA-F]+)\s+<(.*)>:$/) {
$function = $2;
next;
}
if (/^\s*([0-9a-fA-F]+):\s+R_\S+\s+(\S+\(.*\))\S*\s*$/) {
my $sym = $2;
if ( defined $function
&& $function !~ /^($ignore_funcs)(\(.*\))?$/
&& defined $init_syms{$sym}) {
$source = $file unless defined $source;
(my $func_pretty = $function) =~ s/_GLOBAL__I\.\d+_//;
$func_pretty = `echo '$func_pretty' | ${target}c++filt`;
chomp $func_pretty;
print STDERR "$source: $warn: $func_pretty uses initcall ($sym) from normal text section\n";
$error++ if $werror;
}
next;
}
}
}
exit(1) if $error;