Commit 5aea50b5c76b07f2b6bda3426dba998156eaf6d0
Committed by
Linus Torvalds
1 parent
d6624f996a
Exists in
master
and in
4 other branches
scripts: script from kerneloops.org to pretty print oops dumps
We're struggling all the time to figure out where the code came from that oopsed.. The script below (a adaption from a script used by kerneloops.org) can help developers quite a bit, at least for non-module cases. It works and looks like this: [/home/arjan/linux]$ dmesg | perl scripts/markup_oops.pl vmlinux { struct agp_memory *memory; memory = agp_allocate_memory(agp_bridge, pg_count, type); c055c10f: 89 c2 mov %eax,%edx if (memory == NULL) c055c111: 74 19 je c055c12c <agp_allocate_memory_wrap+0x30> /* This function must only be called when current_controller != NULL */ static void agp_insert_into_pool(struct agp_memory * temp) { struct agp_memory *prev; prev = agp_fe.current_controller->pool; c055c113: a1 ec dc 8f c0 mov 0xc08fdcec,%eax *c055c118: 8b 40 10 mov 0x10(%eax),%eax <----- faulting instruction if (prev != NULL) { c055c11b: 85 c0 test %eax,%eax c055c11d: 74 05 je c055c124 <agp_allocate_memory_wrap+0x28> prev->prev = temp; c055c11f: 89 50 04 mov %edx,0x4(%eax) temp->next = prev; c055c122: 89 02 mov %eax,(%edx) } agp_fe.current_controller->pool = temp; c055c124: a1 ec dc 8f c0 mov 0xc08fdcec,%eax c055c129: 89 50 10 mov %edx,0x10(%eax) if (memory == NULL) return NULL; agp_insert_into_pool(memory); so in this case, we faulted while dereferencing agp_fe.current_controller pointer, and we get to see exactly which function and line it affects... Personally I find this very useful, and I can see value for having this script in the kernel for more-than-just-me to use. Caveats: * It only works for oopses not-in-modules * It only works nicely for kernels compiled with CONFIG_DEBUG_INFO * It's not very fast. * It only works on x86 Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 162 additions and 0 deletions Side-by-side Diff
scripts/markup_oops.pl
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 <arjan@linux.intel.com> | |
13 | + | |
14 | + | |
15 | +my $vmlinux_name = $ARGV[0]; | |
16 | + | |
17 | +# | |
18 | +# Step 1: Parse the oops to find the EIP value | |
19 | +# | |
20 | + | |
21 | +my $target = "0"; | |
22 | +while (<STDIN>) { | |
23 | + if ($_ =~ /EIP: 0060:\[\<([a-z0-9]+)\>\]/) { | |
24 | + $target = $1; | |
25 | + } | |
26 | +} | |
27 | + | |
28 | +if ($target =~ /^f8/) { | |
29 | + print "This script does not work on modules ... \n"; | |
30 | + exit; | |
31 | +} | |
32 | + | |
33 | +if ($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 | + | |
40 | +my $counter = 0; | |
41 | +my $state = 0; | |
42 | +my $center = 0; | |
43 | +my @lines; | |
44 | + | |
45 | +sub 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 | + | |
62 | +my $filename; | |
63 | + | |
64 | +open(FILE, "objdump -dS $vmlinux_name |") || die "Cannot start objdump"; | |
65 | + | |
66 | +while (<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 | + | |
91 | +close(FILE); | |
92 | + | |
93 | +if ($counter == 0) { | |
94 | + print "No matching code found \n"; | |
95 | + exit; | |
96 | +} | |
97 | + | |
98 | +if ($center == 0) { | |
99 | + print "No matching code found \n"; | |
100 | + exit; | |
101 | +} | |
102 | + | |
103 | +my $start; | |
104 | +my $finish; | |
105 | +my $codelines = 0; | |
106 | +my $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 | + | |
111 | +while ($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; | |
131 | +while ($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 | + | |
148 | +my $i; | |
149 | + | |
150 | +my $fulltext = ""; | |
151 | +$i = $start; | |
152 | +while ($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 | + | |
161 | +print $fulltext; |