sub reg_name
{
my ($reg) = @_;
$reg =~ s/r(.)x/e\1x/;
$reg =~ s/r(.)i/e\1i/;
$reg =~ s/r(.)p/e\1p/;
return $reg;
}
sub process_x86_regs
{
my ($line, $cntr) = @_;
my $str = ""; if (length($line) < 40) {
return ""; # not an asm istruction
}
# find the arguments to the instruction if ($line =~ /([0-9a-zA-Z\,\%\(\)\-\+]+)$/) {
$lastword = $1;
} else {
return "";
}
# we need to find the registers that get clobbered, # since their value is no longer relevant for previous # instructions in the stream.
$clobber = $lastword; # first, remove all memory operands, they're read only
$clobber =~ s/\([a-z0-9\%\,]+\)//g; # then, remove everything before the comma, thats the read part
$clobber =~ s/.*\,//g;
# if this is the instruction that faulted, we haven't actually done # the write yet... nothing is clobbered. if ($cntr == 0) {
$clobber = "";
}
foreach $reg (keys(%regs)) {
my $clobberprime = reg_name($clobber);
my $lastwordprime = reg_name($lastword);
my $val = $regs{$reg}; if ($val =~ /^[0]+$/) {
$val = "0";
} else {
$val =~ s/^0*//;
}
# first check if we're clobbering this register; if we do # we print it with a =>, and then delete its value if ($clobber =~ /$reg/ || $clobberprime =~ /$reg/) { if (length($val) > 0) {
$str = $str . " $reg => $val ";
}
$regs{$reg} = "";
$val = "";
} # now check if we're reading this register if ($lastword =~ /$reg/ || $lastwordprime =~ /$reg/) { if (length($val) > 0) {
$str = $str . " $reg = $val ";
}
}
}
return $str;
}
# parse the oops while (<STDIN>) {
my $line = $_; if ($line =~ /EIP: 0060:\[\<([a-z0-9]+)\>\]/) {
$target = $1;
} if ($line =~ /RIP: 0010:\[\<([a-z0-9]+)\>\]/) {
$target = $1;
} if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+0x([0-9a-f]+)\/0x[a-f0-9]/) {
$function = $1;
$func_offset = $2;
} if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+0x([0-9a-f]+)\/0x[a-f0-9]/) {
$function = $1;
$func_offset = $2;
}
# check if it's a module if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
$module = $3;
} if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
$module = $3;
}
parse_x86_regs($line);
}
my $decodestart = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$func_offset");
my $decodestop = Math::BigInt->from_hex("0x$target") + 8192; if ($target eq "0") {
print "No oops found!\n";
usage();
}
# if it's a module, we need to find the .ko file and calculate a load offset if ($module ne "") { if ($modulefile eq "") {
$modulefile = `modinfo -F filename $module`;
chomp($modulefile);
}
$filename = $modulefile; if ($filename eq "") {
print "Module .ko file for $module not found. Aborting\n";
exit;
} # ok so we found the module, now we need to calculate the vma offset
open(FILE, $cross_compile."objdump -dS $filename |") || die "Cannot start objdump"; while (<FILE>) { if ($_ =~ /^([0-9a-f]+) \<$function\>\:/) {
my $fu = $1;
$vmaoffset = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$fu") - Math::BigInt->from_hex("0x$func_offset");
}
}
close(FILE);
}
my $counter = 0;
my $state = 0;
my $center = -1;
my @lines;
my @reglines;
sub InRange {
my ($address, $target) = @_;
my $ad = "0x".$address;
my $ta = "0x".$target;
my $delta = Math::BigInt->from_hex($ad) - Math::BigInt->from_hex($ta);
# start annotating the registers in the asm. # this goes from the oopsing point back, so that the annotator # can track (opportunistically) which registers got written and # whos value no longer is relevant.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.