1#!/usr/bin/perl -w 2 3# Copyright 2008, Intel Corporation 4# 5# This file is part of the Linux kernel 6# 7# This program file is free software; you can redistribute it and/or modify it 8# under the terms of the GNU General Public License as published by the 9# Free Software Foundation; version 2 of the License. 10# 11# Authors: 12# Arjan van de Ven <[email protected]> 13 14 15my $vmlinux_name = $ARGV[0]; 16 17# 18# Step 1: Parse the oops to find the EIP value 19# 20 21my $target = "0"; 22while (<STDIN>) { 23 if ($_ =~ /EIP: 0060:\[\<([a-z0-9]+)\>\]/) { 24 $target = $1; 25 } 26} 27 28if ($target =~ /^f8/) { 29 print "This script does not work on modules ... \n"; 30 exit; 31} 32 33if ($target eq "0") { 34 print "No oops found!\n"; 35 print "Usage: \n"; 36 print " dmesg | perl scripts/markup_oops.pl vmlinux\n"; 37 exit; 38} 39 40my $counter = 0; 41my $state = 0; 42my $center = 0; 43my @lines; 44 45sub InRange { 46 my ($address, $target) = @_; 47 my $ad = "0x".$address; 48 my $ta = "0x".$target; 49 my $delta = hex($ad) - hex($ta); 50 51 if (($delta > -4096) && ($delta < 4096)) { 52 return 1; 53 } 54 return 0; 55} 56 57 58 59# first, parse the input into the lines array, but to keep size down, 60# we only do this for 4Kb around the sweet spot 61 62my $filename; 63 64open(FILE, "objdump -dS $vmlinux_name |") || die "Cannot start objdump"; 65 66while (<FILE>) { 67 my $line = $_; 68 chomp($line); 69 if ($state == 0) { 70 if ($line =~ /^([a-f0-9]+)\:/) { 71 if (InRange($1, $target)) { 72 $state = 1; 73 } 74 } 75 } else { 76 if ($line =~ /^([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+)\:/) { 77 my $val = $1; 78 if (!InRange($val, $target)) { 79 last; 80 } 81 if ($val eq $target) { 82 $center = $counter; 83 } 84 } 85 $lines[$counter] = $line; 86 87 $counter = $counter + 1; 88 } 89} 90 91close(FILE); 92 93if ($counter == 0) { 94 print "No matching code found \n"; 95 exit; 96} 97 98if ($center == 0) { 99 print "No matching code found \n"; 100 exit; 101} 102 103my $start; 104my $finish; 105my $codelines = 0; 106my $binarylines = 0; 107# now we go up and down in the array to find how much we want to print 108 109$start = $center; 110 111while ($start > 1) { 112 $start = $start - 1; 113 my $line = $lines[$start]; 114 if ($line =~ /^([a-f0-9]+)\:/) { 115 $binarylines = $binarylines + 1; 116 } else { 117 $codelines = $codelines + 1; 118 } 119 if ($codelines > 10) { 120 last; 121 } 122 if ($binarylines > 20) { 123 last; 124 } 125} 126 127 128$finish = $center; 129$codelines = 0; 130$binarylines = 0; 131while ($finish < $counter) { 132 $finish = $finish + 1; 133 my $line = $lines[$finish]; 134 if ($line =~ /^([a-f0-9]+)\:/) { 135 $binarylines = $binarylines + 1; 136 } else { 137 $codelines = $codelines + 1; 138 } 139 if ($codelines > 10) { 140 last; 141 } 142 if ($binarylines > 20) { 143 last; 144 } 145} 146 147 148my $i; 149 150my $fulltext = ""; 151$i = $start; 152while ($i < $finish) { 153 if ($i == $center) { 154 $fulltext = $fulltext . "*$lines[$i] <----- faulting instruction\n"; 155 } else { 156 $fulltext = $fulltext . " $lines[$i]\n"; 157 } 158 $i = $i +1; 159} 160 161print $fulltext; 162 163