Add a suggestion to use `backtrace' and a reference to the manual to
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 1 Jan 2005 23:21:51 +0000 (23:21 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 1 Jan 2005 23:21:51 +0000 (23:21 +0000)
the message printed by debug_panic().
Improve backtrace program.
Document improvements.

doc/debug.texi
src/lib/debug.c
src/utils/backtrace

index f93eeda3ad0251375e96f8ac02b31ad06bd0aa60..f36ae4a8bc30d4d2fd8793bc84fea5a87547c9dc 100644 (file)
@@ -240,6 +240,17 @@ The results look like this:
 0x8048ac8: _start (../../src/lib/user/entry.c:9)
 @end example
 
+Here's an extra tip for anyone who read this far: @command{backtrace}
+is smart enough to strip the @code{Call stack:} header and @samp{.}
+trailer from the command line if you include them.  This can save you
+a little bit of trouble in cutting and pasting.  Thus, the following
+command prints the same output as the first one we used:
+
+@example
+backtrace kernel.o Call stack: 0xc0106eff 0xc01102fb 0xc010dc22
+0xc010cf67 0xc0102319 0xc010325a 0x804812c 0x8048a96 0x8048ac8.
+@end example
+
 @node i386-elf-gdb
 @section @command{i386-elf-gdb}
 
index 6d75e7a34c47bf25332d5a9cc24ac9cc153c217b..4f0f5f303cf933dab61c1b1e6f723d7ed7b8bb6b 100644 (file)
@@ -88,6 +88,10 @@ debug_panic (const char *file, int line, const char *function,
 
   debug_backtrace ();
 
+  printf ("The `backtrace' program can make call stacks useful.\n"
+          "Read \"Backtraces\" in the \"Debugging Tools\" chapter\n"
+          "of the Pintos documentation for more information.\n");
+  
 #ifdef KERNEL
   serial_flush ();
   if (power_off_when_done)
index 300df642d4927f733f22795e6411c5d2aef08808..487e224791388de739f57fdd512e75b69a579fd8 100755 (executable)
@@ -1,19 +1,56 @@
-#! /usr/bin/perl
-$a2l = search_path ("i386-elf-addr2line") || search_path ("addr2line");
-$bin = shift @ARGV;
-open (A2L, "$a2l -fe $bin " . join (' ', @ARGV) . "|");
-while ($function = <A2L>) {
-    $line = <A2L>;
-    chomp $function;
-    chomp $line;
-    print shift (@ARGV), ": $function ($line)\n";
+#! /usr/bin/perl -w
+
+use strict;
+
+# Check command line.
+if (grep ($_ eq '-h' || $_ eq '--help', @ARGV)) {
+    print "backtrace, for converting raw addresses into symbolic backtraces\n";
+    print "\n";
+    print "usage: backtrace BINARY ADDRESS...\n";
+    print "where BINARY is the binary file from which to obtain symbols\n";
+    print "  and each ADDRESS is a raw address to convert to a symbol name.\n";
+    print "\n";
+    print "In use with Pintos, BINARY is usually kernel.o and the ADDRESS\n";
+    print "list is taken from the \"Call stack:\" printed by the kernel.\n";
+    print "Read \"Backtraces\" in the \"Debugging Tools\" chapter\n";
+    print "of the Pintos documentation for more information.\n";
+    exit 0;
+}
+die "backtrace: binary file argument required (use --help for help)\n"
+    if @ARGV == 0;
+die "backtrace: at least one address argument required (use --help for help)\n"
+    if @ARGV == 1;
+
+# Find binary file.
+my ($bin) = shift @ARGV;
+die "backtrace: $bin: not found (use --help for help)\n"
+    if ! -e $bin;
+
+# Find addr2line.
+my ($a2l) = search_path ("i386-elf-addr2line") || search_path ("addr2line");
+if (!$a2l) {
+    die "backtrace: neither `i386-elf-addr2line' nor `addr2line' in PATH\n";
 }
-   
 sub search_path {
     my ($target) = @_;
-    for $dir (split (':', $ENV{PATH})) {
+    for my $dir (split (':', $ENV{PATH})) {
        my ($file) = "$dir/$target";
        return $file if -e $file;
     }
-    return 0;
+    return undef;
 }
+
+# Drop leading and trailing garbage inserted by kernel.
+shift while grep (/call|stack/i, $ARGV[0]);
+s/\.$// foreach @ARGV;
+
+# Do backtrace.
+open (A2L, "$a2l -fe $bin " . join (' ', @ARGV) . "|");
+while (<A2L>) {
+    my ($function, $line);
+    chomp ($function = $_);
+    chomp ($line = <A2L>);
+    print shift (@ARGV), ": $function ($line)\n";
+}
+close (A2L);
+