154 lines
3.7 KiB
Perl
Executable File
154 lines
3.7 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, ("_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;
|