Commit | Line | Data |
---|---|---|
805e021f CE |
1 | #!/usr/bin/perl |
2 | ||
3 | # decode-panic - decode a Mac OS panic log to show source line numbers | |
4 | # see the end of the file for full documentation and license. | |
5 | ||
6 | use Carp; | |
7 | use English qw( -no_match_vars ) ; | |
8 | use File::Basename; | |
9 | use File::Temp qw( tempdir ); | |
10 | use Getopt::Long; | |
11 | use IO::Dir; | |
12 | use IO::File; | |
13 | use Pod::Usage; | |
14 | use bigint qw/hex/; | |
15 | use warnings; | |
16 | use strict; | |
17 | ||
18 | my $panic_file = "/Library/Logs/panic.log"; | |
19 | my %crash_info; | |
20 | my $backtrace; | |
21 | my $debugkit = ""; | |
22 | my $archive = ""; | |
23 | my $dmgutil = ""; | |
24 | my $kextload = "/sbin/kextload"; | |
25 | my $kextutil = "/usr/bin/kextutil"; | |
26 | my $kextprog; | |
27 | my $gdb = "/usr/bin/gdb"; | |
28 | my $gdbarch = ""; | |
29 | my $kextarch = ""; | |
30 | my $gdb_file = "gdb.input"; | |
31 | my $temp_dir = tempdir( "afsdebugXXXXXX", DIR => File::Spec->tmpdir, | |
32 | TMPDIR => 1, CLEANUP => 1 ); | |
33 | my $dump_file = "/var/db/openafs/logs/crash.dump"; | |
34 | my $kernel = "/mach_kernel"; | |
35 | my $kextpath = "/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext"; | |
36 | my $sysextpath = ""; | |
37 | ||
38 | my $option_quiet; | |
39 | my $option_verbose; | |
40 | my $option_help; | |
41 | my $result = GetOptions ("input=s" => \$panic_file, | |
42 | "output=s" => \$dump_file, | |
43 | "sysexts=s" => \$sysextpath, | |
44 | "kernel=s" => \$kernel, | |
45 | "debugkit=s" => \$debugkit, | |
46 | "archive=s"=> \$archive, | |
47 | "util=s" => \$dmgutil, | |
48 | "verbose" => \$option_verbose, | |
49 | "quiet" => \$option_quiet, | |
50 | "help" => \$option_help | |
51 | ); | |
52 | ||
53 | if ( !$result ) { | |
54 | pod2usage(-message => "Syntax error.", | |
55 | -exitval => 2, | |
56 | -verbose => 1, | |
57 | -output => \*STDERR); | |
58 | ||
59 | exit; | |
60 | } | |
61 | ||
62 | if ($option_help) { | |
63 | pod2usage(-message => "", | |
64 | -exitval => 2, | |
65 | -verbose => 3, | |
66 | -output => \*STDERR); | |
67 | exit; | |
68 | } | |
69 | ||
70 | # check for necessary programs & panic file | |
71 | for my $program ( $gdb, $kextload ) { | |
72 | if ( ! -x $program ) { | |
73 | if ( $option_quiet ) { | |
74 | exit 1; | |
75 | } else { | |
76 | croak "Can't find $program!\n" | |
77 | } | |
78 | } | |
79 | } | |
80 | ||
81 | if ( -x $kextutil ) { | |
82 | $kextprog = $kextutil; | |
83 | } else { | |
84 | $kextprog = $kextload; | |
85 | } | |
86 | ||
87 | croak "Can't find panic file: $panic_file!\n" if ( ! -r $panic_file ); | |
88 | ||
89 | $crash_info{"warning"} = ""; | |
90 | ||
91 | read_panic( $panic_file, \%crash_info ); | |
92 | ||
93 | if ($crash_info{"kernel_version"} =~ /X86_64/ ) { | |
94 | $gdbarch="-a x86_64"; | |
95 | $kextarch="x86_64"; | |
96 | } else { | |
97 | if ($crash_info{"kernel_version"} =~ /I386/ ) { | |
98 | $gdbarch="-a i386"; | |
99 | $kextarch="i386"; | |
100 | } else { | |
101 | if ($crash_info{"kernel_version"} =~ /PPC/ ) { | |
102 | $gdbarch="-a ppc"; | |
103 | $kextarch="ppc"; | |
104 | } | |
105 | } | |
106 | } | |
107 | ||
108 | if (-d $debugkit && -f $dmgutil ) { | |
109 | extract_kernel( $crash_info{"kernel_version"}, $temp_dir, $debugkit, $dmgutil ); | |
110 | $kernel = "$temp_dir/mach_kernel"; | |
111 | } | |
112 | ||
113 | if (-d $archive && -f $dmgutil ) { | |
114 | extract_openafs( $crash_info{"afs_info"}, $temp_dir, $archive, $crash_info{"kernel_version"}, $dmgutil ); | |
115 | if (-d "$temp_dir/Library/OpenAFS/Debug/afs.kext" ) { | |
116 | $kextpath = "$temp_dir/Library/OpenAFS/Debug/afs.kext"; | |
117 | } else { | |
118 | $kextpath = "$temp_dir/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext"; | |
119 | } | |
120 | } | |
121 | ||
122 | generate_symbol_files( $crash_info{"afs_kernel_address"}, $crash_info{"kernel_shift"}, $temp_dir, $kextarch , $kernel, $kextpath, $sysextpath); | |
123 | ||
124 | write_gdb_input_file( $temp_dir, $gdb_file, $crash_info{ "backtrace" }, $crash_info{ "kernel_shift" } ); | |
125 | ||
126 | # needed so we can put the sym file where the kext is. ick. | |
127 | if ($kextprog eq $kextutil) { | |
128 | `cp -R $kextpath $temp_dir`; | |
129 | } | |
130 | ||
131 | if ($option_verbose) { | |
132 | print "$gdb $gdbarch $kernel -batch -x $temp_dir/$gdb_file\n"; | |
133 | my $gdbi_fh = IO::File->new( $temp_dir . "/" . $gdb_file, '<' ) | |
134 | or croak "Can't open backtrace file $gdb_file: $OS_ERROR\n"; | |
135 | while (my $line = <$gdbi_fh> ) { | |
136 | print $line; | |
137 | } | |
138 | $gdbi_fh->close() | |
139 | or croak "Can't close file $gdb_file: $OS_ERROR\n"; | |
140 | } | |
141 | my $gdb_output = `$gdb $gdbarch $kernel -batch -x $temp_dir/$gdb_file`; | |
142 | croak "gdb failed!\n" if $CHILD_ERROR; | |
143 | ||
144 | write_dump_file( $dump_file, \%crash_info, $gdb_output ); | |
145 | ||
146 | sub extract_openafs { | |
147 | my $oversion = shift; | |
148 | my $tempdir = shift; | |
149 | my $oarchive = shift; | |
150 | my $kversion = shift; | |
151 | my $hdutil = shift; | |
152 | ||
153 | $kversion =~ /Darwin Kernel Version ([0-9]+).[0-9]+.[0-9]+:/; | |
154 | my $major = $1; | |
155 | $major -= 4; | |
156 | ||
157 | $oversion =~ /org.openafs.filesystems.afs\(([0-9.abcf]+)\)/; | |
158 | my $vers = $1; | |
159 | $vers =~ s/fc/pre/; | |
160 | $vers =~ s/f/pre/; | |
161 | my $dmgvers = $vers; | |
162 | if ($vers =~ /([0-9]+)f([0-9]+)/) { | |
163 | $dmgvers = "$1" . "." . "$2"; | |
164 | $vers = "$1"; | |
165 | } | |
166 | ||
167 | my $odmg = "$oarchive/$vers/macos-10.${major}/OpenAFS-$vers-\*.dmg"; | |
168 | if ($option_verbose) { | |
169 | print "$hdutil $odmg extractall OpenAFS.pkg $tempdir/OpenAFS.pkg\n"; | |
170 | } | |
171 | `$hdutil $odmg extractall OpenAFS.pkg $tempdir/OpenAFS.pkg`; | |
172 | if ($option_verbose) { | |
173 | print "cd $tempdir && gzcat $tempdir/OpenAFS.pkg/Contents/Archive.pax.gz | pax -r ./Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext\n"; | |
174 | } | |
175 | `cd $tempdir && gzcat $tempdir/OpenAFS.pkg/Contents/Archive.pax.gz | pax -r ./Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext`; | |
176 | if ($option_verbose) { | |
177 | print "$hdutil $odmg extractall OpenAFS-debug-extension.pkg $tempdir/OpenAFS-debug-extension.pkg\n"; | |
178 | } | |
179 | `$hdutil $odmg extractall OpenAFS-debug-extension.pkg $tempdir/OpenAFS-debug-extension.pkg`; | |
180 | if (-f "$tempdir/OpenAFS-debug-extension.pkg/Contents/Archive.pax.gz" ) { | |
181 | if ($option_verbose) { | |
182 | print "cd $tempdir && gzcat $tempdir/OpenAFS-debug-extension.pkg/Contents/Archive.pax.gz | pax -r ./Library/OpenAFS/Debug/afs.kext.dSYM\n"; | |
183 | } | |
184 | `cd $tempdir && gzcat $tempdir/OpenAFS-debug-extension.pkg/Contents/Archive.pax.gz | pax -r ./Library/OpenAFS/Debug/afs.kext.dSYM`; | |
185 | if ($option_verbose) { | |
186 | print "cd $tempdir && gzcat $tempdir/OpenAFS-debug-extension.pkg/Contents/Archive.pax.gz | pax -r ./Library/OpenAFS/Debug/afs.kext\n"; | |
187 | } | |
188 | `cd $tempdir && gzcat $tempdir/OpenAFS-debug-extension.pkg/Contents/Archive.pax.gz | pax -r ./Library/OpenAFS/Debug/afs.kext`; | |
189 | } | |
190 | } | |
191 | ||
192 | sub extract_kernel { | |
193 | my $kversion = shift; | |
194 | my $tempdir = shift; | |
195 | my $debugarchive = shift; | |
196 | my $hdutil = shift; | |
197 | ||
198 | $kversion =~ /Darwin Kernel Version ([0-9]+).([0-9]+).[0-9]+:/; | |
199 | my $minor = $2; | |
200 | my $major = $1; | |
201 | $major -= 4; | |
202 | my $kdk = "$debugarchive/kernel_debug_kit_10.${major}.${minor}_\*.dmg"; | |
203 | if ($option_verbose) { | |
204 | print "$hdutil $kdk extractall System.kext $tempdir/System.kext\n"; | |
205 | } | |
206 | `$hdutil $kdk extractall System.kext $tempdir/System.kext`; | |
207 | if ($option_verbose) { | |
208 | print "$hdutil $kdk extractall mach_kernel.dSYM $tempdir/mach_kernel.dSYM\n"; | |
209 | } | |
210 | `$hdutil $kdk extractall mach_kernel.dSYM $tempdir/mach_kernel.dSYM`; | |
211 | if ($option_verbose) { | |
212 | print "$hdutil $kdk extract mach_kernel $tempdir/mach_kernel\n"; | |
213 | } | |
214 | `$hdutil $kdk extract mach_kernel $tempdir/mach_kernel`; | |
215 | } | |
216 | ||
217 | ||
218 | # read the panic file and parse out the addresses | |
219 | sub read_panic { | |
220 | ||
221 | my $filename = shift; | |
222 | my $hash_ref = shift; | |
223 | ||
224 | my $kernel_line; | |
225 | my $line; | |
226 | my @panic_section_positions = ( 0 ); | |
227 | ||
228 | my $panic_fh = IO::File->new( $filename, '<' ) | |
229 | or croak "Can't open backtrace file $filename: $OS_ERROR\n"; | |
230 | ||
231 | # find the last panic section as denoted by "*********" | |
232 | while ( $line = <$panic_fh> ) { | |
233 | chomp $line; | |
234 | if ( $line eq "*********" ) { | |
235 | # skip a line | |
236 | $line = <$panic_fh>; | |
237 | push @panic_section_positions, $panic_fh->tell; | |
238 | } | |
239 | } | |
240 | ||
241 | # ignore the empty last section | |
242 | if ( @panic_section_positions > 2 ) { | |
243 | pop @panic_section_positions | |
244 | } | |
245 | ||
246 | # Seek to last full panic section | |
247 | # or the beginning of the file if appropriate | |
248 | $panic_fh->seek( $panic_section_positions[-1], 0 ); | |
249 | ||
250 | $hash_ref->{ "date" } = <$panic_fh>; | |
251 | chomp $hash_ref->{ "date" }; | |
252 | ||
253 | while ( $line = <$panic_fh> ) { | |
254 | chomp $line; | |
255 | ||
256 | #skip lines until "Backtrace" is seen | |
257 | $line =~ /^\s*(Backtrace,|Backtrace:|Backtrace \()/; | |
258 | $backtrace = $1; | |
259 | last if $backtrace; | |
260 | } | |
261 | ||
262 | if ( !$backtrace ) { | |
263 | if ( $option_quiet ) { | |
264 | exit 1; | |
265 | } else { | |
266 | croak "Couldn't find a backtrace in $filename\n"; | |
267 | } | |
268 | } | |
269 | ||
270 | # gather the backtrace addresses | |
271 | if ( $backtrace eq "Backtrace:" ) { | |
272 | # ppc format panic | |
273 | while ( $line = <$panic_fh> ) { | |
274 | chomp $line; | |
275 | last if $line !~ /^\s*(0x[0-9a-fA-F]+)/; | |
276 | my @memory_addresses = split /\s+/, $line; | |
277 | ||
278 | # add non-empty array elements to the list | |
279 | push @{ $hash_ref->{ "backtrace" } }, | |
280 | grep { /0x/ } @memory_addresses; | |
281 | } | |
282 | } else { | |
283 | # intel format panic | |
284 | while ( $line = <$panic_fh> ) { | |
285 | chomp $line; | |
286 | last if $line !~ /^\s*0x[0-9a-fA-F]+ : (0x[0-9a-fA-F]*)/; | |
287 | push @{ $hash_ref->{ "backtrace" } }, $1; | |
288 | } | |
289 | } | |
290 | ||
291 | # now we need the address for the afs kernel module | |
292 | while ( $line = <$panic_fh> ) { | |
293 | chomp $line; | |
294 | last if ($line =~ /^BSD\s+process/ ); | |
295 | next if ( $line !~ /org\.openafs\.filesystems\.afs/ ); | |
296 | ||
297 | $kernel_line = $line; | |
298 | $line =~ /\@(0x[0-9a-fA-F]+)/; | |
299 | $hash_ref->{ "afs_kernel_address" } = $1; | |
300 | $kernel_line =~ /^\s+([^@]+)@.+/; | |
301 | $hash_ref->{ "afs_info" } = $1; | |
302 | ||
303 | last; | |
304 | } | |
305 | ||
306 | $hash_ref->{ "kernel_shift" } = "0x0"; | |
307 | # grab the kernel version | |
308 | while ( $line = <$panic_fh> ) { | |
309 | chomp $line; | |
310 | if ( $line =~ /^Darwin Kernel Version/ ) { | |
311 | $hash_ref->{ "kernel_version" } = $line; | |
312 | next; | |
313 | } | |
314 | if ($line =~ /^Kernel slide:\s+(0x[0-9a-fA-F]+)/ ) { | |
315 | $hash_ref->{ "kernel_shift" } = $1; | |
316 | next; | |
317 | } | |
318 | next if (! $hash_ref->{ "kernel_version" }); | |
319 | last if ($line =~ /^\s*$/) | |
320 | } | |
321 | ||
322 | if (! $kernel_line ) { | |
323 | #unloaded? | |
324 | while ( $line = <$panic_fh> ) { | |
325 | chomp $line; | |
326 | last if ( $line =~ /^loaded\s+kexts:/ ); | |
327 | next if ( $line !~ /org\.openafs\.filesystems\.afs/ ); | |
328 | $kernel_line = $line; | |
329 | $line =~ /org\.openafs\.filesystems\.afs\s+([^@]+)\s+\(addr\s+(0x[0-9a-fA-F]+),/; | |
330 | $hash_ref->{ "afs_kernel_address" } = $2; | |
331 | $hash_ref->{ "afs_info" } = "org.openafs.filesystems.afs(" . $1 . ")\@0x" . $2; | |
332 | $hash_ref->{ "warning" } = "MODULE WAS UNLOADED!\n"; | |
333 | } | |
334 | } | |
335 | ||
336 | $panic_fh->close() | |
337 | or croak "Can't close file $filename: $OS_ERROR\n"; | |
338 | ||
339 | if ( !$kernel_line ) { | |
340 | if ( $option_quiet ) { | |
341 | exit 1; | |
342 | } else { | |
343 | croak "No OpenAFS reference found in latest panic!"; | |
344 | } | |
345 | } | |
346 | } | |
347 | ||
348 | # generate the symbol files that will be read by gdb | |
349 | sub generate_symbol_files { | |
350 | my $kernel_address = shift; | |
351 | my $kernel_shift = shift; | |
352 | my $symbol_write_dir = shift; | |
353 | my $kextarch = shift; | |
354 | my $kernel = shift; | |
355 | my $kext = shift; | |
356 | my $sysext = shift; | |
357 | ||
358 | my $kaddress = sprintf("0x%x", hex($kernel_address) - hex($kernel_shift)); | |
359 | ||
360 | if ($kextprog eq $kextload) { | |
361 | if ($kernel eq "/mach_kernel") { | |
362 | if ($option_verbose) { | |
363 | print "$kextprog -k $kernel -s $temp_dir -a org.openafs.filesystems.afs\@${kaddress} -n $kext\n"; | |
364 | } | |
365 | system( $kextprog, | |
366 | "-k", $kernel, | |
367 | "-s", $temp_dir, | |
368 | "-a", 'org.openafs.filesystems.afs@' . $kaddress, | |
369 | "-n", $kext ); | |
370 | } else { | |
371 | if ($option_verbose) { | |
372 | print "$kextprog -c -e -r $temp_dir -k $kernel -s $temp_dir -a org.openafs.filesystems.afs\@${kaddress} -n $kext\n"; | |
373 | } | |
374 | system( $kextprog, | |
375 | "-c", "-e", | |
376 | "-r", $temp_dir, | |
377 | "-k", $kernel, | |
378 | "-s", $temp_dir, | |
379 | "-a", 'org.openafs.filesystems.afs@' . $kaddress, | |
380 | "-n", $kext ); | |
381 | } | |
382 | } else { | |
383 | if ($kernel eq "/mach_kernel") { | |
384 | if ($option_verbose) { | |
385 | print "$kextprog -k $kernel -s $temp_dir -arch $kextarch -a org.openafs.filesystems.afs\@${kaddress} -n $kext\n"; | |
386 | } | |
387 | system( $kextprog, | |
388 | "-k", $kernel, | |
389 | "-s", $temp_dir, | |
390 | "-arch", $kextarch, | |
391 | "-a", 'org.openafs.filesystems.afs@' . $kaddress, | |
392 | "-n", $kext ); | |
393 | } else { | |
394 | if ($option_verbose) { | |
395 | if ($sysextpath) { | |
396 | print "$kextprog -c -e -r $sysextpath -r $temp_dir -k $kernel -s $temp_dir -arch $kextarch -a org.openafs.filesystems.afs\@${kaddress} -n $kext\n"; | |
397 | } else { | |
398 | print "$kextprog -c -e -r $temp_dir -k $kernel -s $temp_dir -arch $kextarch -a org.openafs.filesystems.afs\@${kaddress} -n $kext\n"; | |
399 | } | |
400 | } | |
401 | if ($sysextpath) { | |
402 | system( $kextprog, | |
403 | "-c", "-e", | |
404 | "-r", $temp_dir, | |
405 | "-r", $sysextpath, | |
406 | "-k", $kernel, | |
407 | "-s", $temp_dir, | |
408 | "-arch", $kextarch, | |
409 | "-a", 'org.openafs.filesystems.afs@' . $kaddress, | |
410 | "-n", $kext ); | |
411 | } else { | |
412 | system( $kextprog, | |
413 | "-c", "-e", | |
414 | "-r", $temp_dir, | |
415 | "-k", $kernel, | |
416 | "-s", $temp_dir, | |
417 | "-arch", $kextarch, | |
418 | "-a", 'org.openafs.filesystems.afs@' . $kaddress, | |
419 | "-n", $kext ); | |
420 | } | |
421 | } | |
422 | } | |
423 | if ( $CHILD_ERROR ) { | |
424 | # error | |
425 | croak "kextload failed to run: $OS_ERROR\n"; | |
426 | } | |
427 | } | |
428 | ||
429 | ||
430 | sub write_gdb_input_file { | |
431 | ||
432 | my $write_dir = shift; | |
433 | my $filename = shift; | |
434 | my $backtrace_ref = shift; | |
435 | my $kernel_shift = shift; | |
436 | ||
437 | my @symbol_files = ( $write_dir . "/org.openafs.filesystems.afs.sym" ); | |
438 | ||
439 | my $fh = IO::File->new( $write_dir . "/" . $filename, '>' ) | |
440 | or croak "Can't open gdb file $filename for writing: $OS_ERROR\n"; | |
441 | ||
442 | if ($kextprog eq $kextutil) { | |
443 | print $fh "add-kext " . $write_dir . "/afs.kext\n"; | |
444 | } else { | |
445 | for my $symbol ( @symbol_files ) { | |
446 | print $fh "add-symbol-file $symbol\n"; | |
447 | } | |
448 | } | |
449 | ||
450 | print $fh "set print asm-demangle on\n"; | |
451 | ||
452 | for my $address ( @{ $backtrace_ref } ) { | |
453 | my $kaddress = sprintf("0x%x", hex($address) - hex($kernel_shift)); | |
454 | print $fh "x/i $kaddress\n"; | |
455 | } | |
456 | ||
457 | $fh->close() | |
458 | or croak "Can't close file $filename: $OS_ERROR\n"; | |
459 | } | |
460 | ||
461 | # write out the pertinent details to a file. | |
462 | sub write_dump_file { | |
463 | my $filename = shift; | |
464 | my $hash_ref = shift; | |
465 | my $output = shift; | |
466 | ||
467 | my $log_dir = dirname $filename; | |
468 | ||
469 | if ( ! -d $log_dir ) { | |
470 | mkdir $log_dir, 0755; | |
471 | croak "Can't create directory $log_dir: $OS_ERROR\n" if $CHILD_ERROR; | |
472 | } | |
473 | ||
474 | croak "Can't write to folder $log_dir." if ( ! -w $log_dir ); | |
475 | ||
476 | my $fh = IO::File->new( $filename, '>', 0664 ) | |
477 | or croak "Can't open dump file $filename for writing: $OS_ERROR\n"; | |
478 | ||
479 | print $fh "Panic Date: ", $hash_ref->{ "date" }, "\n"; | |
480 | print $fh "Kernel Version: ", $hash_ref->{ "kernel_version" }, "\n"; | |
481 | print $fh "OpenAFS Version: ", $hash_ref->{ "afs_info" }, "\n"; | |
482 | print $fh $hash_ref->{ "warning" }; | |
483 | print $fh "=============\n"; | |
484 | print $fh $output; | |
485 | ||
486 | $fh->close() | |
487 | or croak "Can't close file $filename: $OS_ERROR\n"; | |
488 | } | |
489 | ||
490 | __END__ | |
491 | ||
492 | =head1 NAME | |
493 | ||
494 | decode-panic - decode a Mac OS panic log to show source line numbers | |
495 | ||
496 | =head1 VERSION | |
497 | ||
498 | This documentation refers to decode-panic version $Revision$ | |
499 | ||
500 | =head1 SYNOPSIS | |
501 | ||
502 | decode-panic [-i <input panic log>] [-o <output dump file>] [-k <kernel file>] [-d <kernel debug kit archive>] [-a <openafs package archive>] [-u <path to hdutil>] [-q] [-v] | |
503 | ||
504 | =head1 OPTIONS | |
505 | ||
506 | -i The path to the panic log that should be read | |
507 | -o The path to where the decoded panic log should be written | |
508 | -k The path to the kernel image corresponding to the panic | |
509 | -d The path to a directory containing kernel debug kit dmgs | |
510 | -a The path to an archive of OpenAFS installer dmgs | |
511 | -u The path to the hdutil dmg utility program | |
512 | -q Quiet mode - don't complain if there is a problem. | |
513 | -v Verbose mode - print all commands. | |
514 | -h print full help | |
515 | ||
516 | =head1 DESCRIPTION | |
517 | ||
518 | This tool parses the panic log for Mac OS X kernel panics that are caused by | |
519 | openafs in order to produce a human-readable backtrace. | |
520 | ||
521 | This program uses crash isolation procedure as outlined in | |
522 | http://developer.apple.com/technotes/tn2002/tn2063.html#IsolatingCrash | |
523 | ||
524 | Here is an example file that is fed to gdb: | |
525 | ||
526 | add-symbol-file /tmp/afsdebugt8dGOb/org.openafs.filesystems.afs.sym | |
527 | set print asm-demangle on | |
528 | x/i 0x2ED1F7C0 | |
529 | x/i 0x2ED0D1A4 | |
530 | ||
531 | Panic logs can be found in /Library/Logs/panic.log in 10.4 (Tiger), | |
532 | /Library/Logs/PanicReporter/YYYY-MM-DD-HHMMSS.panic in 10.5 (Leopard), | |
533 | and /Library/Logs/DiagnosticReports/Kernel_YYYY-MM-DD-HHMMSS.panic in 10.6 | |
534 | (SnowLeopard). | |
535 | ||
536 | =head1 DEPENDENCIES | |
537 | ||
538 | This program needs gdb and kextload; Starting in SnowLeopard, it needs kextutil. | |
539 | ||
540 | Batch decoding requires a directory of Kernel Debug Kit DMGs, a directory of | |
541 | OpenAFS installer DMGs, and the DMG extraction utility currently available | |
542 | in source form at http://www.dementia.org/~shadow/dmgutil-0.1.tar.gz | |
543 | ||
544 | =head1 BUGS AND LIMITATIONS | |
545 | ||
546 | decode-panic clobbers the output file. | |
547 | ||
548 | =head1 AUTHOR | |
549 | ||
550 | Copyright 2008-2010. Jason Edgecombe <jason@rampaginggeek.com> and others. | |
551 | ||
552 | This documentation is covered by the BSD License as written in the | |
553 | doc/LICENSE file in the OpenAFS source tree. This program was originally | |
554 | written by Jason Edgecombe for OpenAFS. |