diff options
Diffstat (limited to 'scripts/markup_oops.pl')
| -rw-r--r-- | scripts/markup_oops.pl | 54 | 
1 files changed, 39 insertions, 15 deletions
| diff --git a/scripts/markup_oops.pl b/scripts/markup_oops.pl index e950f9cde019..827896f56501 100644 --- a/scripts/markup_oops.pl +++ b/scripts/markup_oops.pl | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | use File::Basename; | 3 | use File::Basename; | 
| 4 | use Math::BigInt; | 4 | use Math::BigInt; | 
| 5 | use Getopt::Long; | ||
| 5 | 6 | ||
| 6 | # Copyright 2008, Intel Corporation | 7 | # Copyright 2008, Intel Corporation | 
| 7 | # | 8 | # | 
| @@ -15,6 +16,16 @@ use Math::BigInt; | |||
| 15 | # Arjan van de Ven <arjan@linux.intel.com> | 16 | # Arjan van de Ven <arjan@linux.intel.com> | 
| 16 | 17 | ||
| 17 | 18 | ||
| 19 | my $cross_compile = ""; | ||
| 20 | my $vmlinux_name = ""; | ||
| 21 | my $modulefile = ""; | ||
| 22 | |||
| 23 | # Get options | ||
| 24 | Getopt::Long::GetOptions( | ||
| 25 | 'cross-compile|c=s' => \$cross_compile, | ||
| 26 | 'module|m=s' => \$modulefile, | ||
| 27 | 'help|h' => \&usage, | ||
| 28 | ) || usage (); | ||
| 18 | my $vmlinux_name = $ARGV[0]; | 29 | my $vmlinux_name = $ARGV[0]; | 
| 19 | if (!defined($vmlinux_name)) { | 30 | if (!defined($vmlinux_name)) { | 
| 20 | my $kerver = `uname -r`; | 31 | my $kerver = `uname -r`; | 
| @@ -23,9 +34,8 @@ if (!defined($vmlinux_name)) { | |||
| 23 | print "No vmlinux specified, assuming $vmlinux_name\n"; | 34 | print "No vmlinux specified, assuming $vmlinux_name\n"; | 
| 24 | } | 35 | } | 
| 25 | my $filename = $vmlinux_name; | 36 | my $filename = $vmlinux_name; | 
| 26 | # | 37 | |
| 27 | # Step 1: Parse the oops to find the EIP value | 38 | # Parse the oops to find the EIP value | 
| 28 | # | ||
| 29 | 39 | ||
| 30 | my $target = "0"; | 40 | my $target = "0"; | 
| 31 | my $function; | 41 | my $function; | 
| @@ -177,26 +187,26 @@ my $decodestart = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex(" | |||
| 177 | my $decodestop = Math::BigInt->from_hex("0x$target") + 8192; | 187 | my $decodestop = Math::BigInt->from_hex("0x$target") + 8192; | 
| 178 | if ($target eq "0") { | 188 | if ($target eq "0") { | 
| 179 | print "No oops found!\n"; | 189 | print "No oops found!\n"; | 
| 180 | print "Usage: \n"; | 190 | usage(); | 
| 181 | print " dmesg | perl scripts/markup_oops.pl vmlinux\n"; | ||
| 182 | exit; | ||
| 183 | } | 191 | } | 
| 184 | 192 | ||
| 185 | # if it's a module, we need to find the .ko file and calculate a load offset | 193 | # if it's a module, we need to find the .ko file and calculate a load offset | 
| 186 | if ($module ne "") { | 194 | if ($module ne "") { | 
| 187 | my $modulefile = `modinfo $module | grep '^filename:' | awk '{ print \$2 }'`; | 195 | if ($modulefile eq "") { | 
| 188 | chomp($modulefile); | 196 | $modulefile = `modinfo -F filename $module`; | 
| 197 | chomp($modulefile); | ||
| 198 | } | ||
| 189 | $filename = $modulefile; | 199 | $filename = $modulefile; | 
| 190 | if ($filename eq "") { | 200 | if ($filename eq "") { | 
| 191 | print "Module .ko file for $module not found. Aborting\n"; | 201 | print "Module .ko file for $module not found. Aborting\n"; | 
| 192 | exit; | 202 | exit; | 
| 193 | } | 203 | } | 
| 194 | # ok so we found the module, now we need to calculate the vma offset | 204 | # ok so we found the module, now we need to calculate the vma offset | 
| 195 | open(FILE, "objdump -dS $filename |") || die "Cannot start objdump"; | 205 | open(FILE, $cross_compile."objdump -dS $filename |") || die "Cannot start objdump"; | 
| 196 | while (<FILE>) { | 206 | while (<FILE>) { | 
| 197 | if ($_ =~ /^([0-9a-f]+) \<$function\>\:/) { | 207 | if ($_ =~ /^([0-9a-f]+) \<$function\>\:/) { | 
| 198 | my $fu = $1; | 208 | my $fu = $1; | 
| 199 | $vmaoffset = hex($target) - hex($fu) - hex($func_offset); | 209 | $vmaoffset = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$fu") - Math::BigInt->from_hex("0x$func_offset"); | 
| 200 | } | 210 | } | 
| 201 | } | 211 | } | 
| 202 | close(FILE); | 212 | close(FILE); | 
| @@ -204,7 +214,7 @@ if ($module ne "") { | |||
| 204 | 214 | ||
| 205 | my $counter = 0; | 215 | my $counter = 0; | 
| 206 | my $state = 0; | 216 | my $state = 0; | 
| 207 | my $center = 0; | 217 | my $center = -1; | 
| 208 | my @lines; | 218 | my @lines; | 
| 209 | my @reglines; | 219 | my @reglines; | 
| 210 | 220 | ||
| @@ -212,7 +222,7 @@ sub InRange { | |||
| 212 | my ($address, $target) = @_; | 222 | my ($address, $target) = @_; | 
| 213 | my $ad = "0x".$address; | 223 | my $ad = "0x".$address; | 
| 214 | my $ta = "0x".$target; | 224 | my $ta = "0x".$target; | 
| 215 | my $delta = hex($ad) - hex($ta); | 225 | my $delta = Math::BigInt->from_hex($ad) - Math::BigInt->from_hex($ta); | 
| 216 | 226 | ||
| 217 | if (($delta > -4096) && ($delta < 4096)) { | 227 | if (($delta > -4096) && ($delta < 4096)) { | 
| 218 | return 1; | 228 | return 1; | 
| @@ -225,7 +235,7 @@ sub InRange { | |||
| 225 | # first, parse the input into the lines array, but to keep size down, | 235 | # first, parse the input into the lines array, but to keep size down, | 
| 226 | # we only do this for 4Kb around the sweet spot | 236 | # we only do this for 4Kb around the sweet spot | 
| 227 | 237 | ||
| 228 | open(FILE, "objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump"; | 238 | open(FILE, $cross_compile."objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump"; | 
| 229 | 239 | ||
| 230 | while (<FILE>) { | 240 | while (<FILE>) { | 
| 231 | my $line = $_; | 241 | my $line = $_; | 
| @@ -236,7 +246,8 @@ while (<FILE>) { | |||
| 236 | $state = 1; | 246 | $state = 1; | 
| 237 | } | 247 | } | 
| 238 | } | 248 | } | 
| 239 | } else { | 249 | } | 
| 250 | if ($state == 1) { | ||
| 240 | if ($line =~ /^([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+)\:/) { | 251 | if ($line =~ /^([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+)\:/) { | 
| 241 | my $val = $1; | 252 | my $val = $1; | 
| 242 | if (!InRange($val, $target)) { | 253 | if (!InRange($val, $target)) { | 
| @@ -259,7 +270,7 @@ if ($counter == 0) { | |||
| 259 | exit; | 270 | exit; | 
| 260 | } | 271 | } | 
| 261 | 272 | ||
| 262 | if ($center == 0) { | 273 | if ($center == -1) { | 
| 263 | print "No matching code found \n"; | 274 | print "No matching code found \n"; | 
| 264 | exit; | 275 | exit; | 
| 265 | } | 276 | } | 
| @@ -344,3 +355,16 @@ while ($i < $finish) { | |||
| 344 | $i = $i +1; | 355 | $i = $i +1; | 
| 345 | } | 356 | } | 
| 346 | 357 | ||
| 358 | sub usage { | ||
| 359 | print <<EOT; | ||
| 360 | Usage: | ||
| 361 | dmesg | perl $0 [OPTION] [VMLINUX] | ||
| 362 | |||
| 363 | OPTION: | ||
| 364 | -c, --cross-compile CROSS_COMPILE Specify the prefix used for toolchain. | ||
| 365 | -m, --module MODULE_DIRNAME Specify the module filename. | ||
| 366 | -h, --help Help. | ||
| 367 | EOT | ||
| 368 | exit; | ||
| 369 | } | ||
| 370 | |||
