5 # Copyright 2008, Intel Corporation
7 # This file is part of the Linux kernel
9 # This program file is free software; you can redistribute it and/or modify it
10 # under the terms of the GNU General Public License as published by the
11 # Free Software Foundation; version 2 of the License.
14 # Arjan van de Ven <arjan@linux.intel.com>
17 my $vmlinux_name = $ARGV[0];
18 if (!defined($vmlinux_name)) {
19 my $kerver = `uname -r`;
21 $vmlinux_name = "/lib/modules/$kerver/build/vmlinux";
22 print "No vmlinux specified, assuming $vmlinux_name\n";
24 my $filename = $vmlinux_name;
26 # Step 1: Parse the oops to find the EIP value
37 if ($line =~ /EIP: 0060:\[\<([a-z0-9]+)\>\]/) {
40 if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]/) {
45 # check if it's a module
46 if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
51 my $decodestart = hex($target) - hex($func_offset);
52 my $decodestop = $decodestart + 8192;
54 print "No oops found!\n";
56 print " dmesg | perl scripts/markup_oops.pl vmlinux\n";
60 # if it's a module, we need to find the .ko file and calculate a load offset
62 my $dir = dirname($filename);
64 my $mod = $module . ".ko";
65 my $modulefile = `find $dir -name $mod | head -1`;
67 $filename = $modulefile;
68 if ($filename eq "") {
69 print "Module .ko file for $module not found. Aborting\n";
72 # ok so we found the module, now we need to calculate the vma offset
73 open(FILE, "objdump -dS $filename |") || die "Cannot start objdump";
75 if ($_ =~ /^([0-9a-f]+) \<$function\>\:/) {
77 $vmaoffset = hex($target) - hex($fu) - hex($func_offset);
89 my ($address, $target) = @_;
90 my $ad = "0x".$address;
91 my $ta = "0x".$target;
92 my $delta = hex($ad) - hex($ta);
94 if (($delta > -4096) && ($delta < 4096)) {
102 # first, parse the input into the lines array, but to keep size down,
103 # we only do this for 4Kb around the sweet spot
105 open(FILE, "objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump";
111 if ($line =~ /^([a-f0-9]+)\:/) {
112 if (InRange($1, $target)) {
117 if ($line =~ /^([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+)\:/) {
119 if (!InRange($val, $target)) {
122 if ($val eq $target) {
126 $lines[$counter] = $line;
128 $counter = $counter + 1;
135 print "No matching code found \n";
140 print "No matching code found \n";
148 # now we go up and down in the array to find how much we want to print
154 my $line = $lines[$start];
155 if ($line =~ /^([a-f0-9]+)\:/) {
156 $binarylines = $binarylines + 1;
158 $codelines = $codelines + 1;
160 if ($codelines > 10) {
163 if ($binarylines > 20) {
172 while ($finish < $counter) {
173 $finish = $finish + 1;
174 my $line = $lines[$finish];
175 if ($line =~ /^([a-f0-9]+)\:/) {
176 $binarylines = $binarylines + 1;
178 $codelines = $codelines + 1;
180 if ($codelines > 10) {
183 if ($binarylines > 20) {
193 while ($i < $finish) {
195 $fulltext = $fulltext . "*$lines[$i] <----- faulting instruction\n";
197 $fulltext = $fulltext . " $lines[$i]\n";