Make tests public. Rewrite most tests. Add tests.
[pintos-anon] / src / utils / backtrace
index 0dd28420e3d4cfb38caade7dfdec1913ddc6d4cb..baa5eff535cd878922e02e0dcaa84a022fce1807 100755 (executable)
@@ -1,19 +1,66 @@
-#! /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 "$function ($line)\n";
+#! /usr/bin/perl -w
+
+use strict;
+
+# Check command line.
+if (grep ($_ eq '-h' || $_ eq '--help', @ARGV)) {
+    print <<'EOF';
+backtrace, for converting raw addresses into symbolic backtraces
+usage: backtrace [BINARY] ADDRESS...
+where BINARY is the binary file from which to obtain symbols
+ and ADDRESS is a raw address to convert to a symbol name.
+
+If BINARY is unspecified, the default is the first of kernel.o or
+build/kernel.o that exists.
+
+The ADDRESS list should be taken from the "Call stack:" printed by the
+kernel.  Read "Backtraces" in the "Debugging Tools" chapter of the
+Pintos documentation for more information.
+EOF
+    exit 0;
+}
+die "backtrace: at least one argument required (use --help for help)\n"
+    if @ARGV == 0;
+
+# Drop leading and trailing garbage inserted by kernel.
+shift while grep (/^(call|stack:?)$/i, $ARGV[0]);
+s/\.$// foreach @ARGV;
+
+# Find binary file.
+my ($bin) = $ARGV[0];
+if (-e $bin) {
+    shift @ARGV;
+} elsif ($bin !~ /^0/) {
+    die "backtrace: $bin: not found (use --help for help)\n";
+} elsif (-e 'kernel.o') {
+    $bin = 'kernel.o';
+} elsif (-e 'build/kernel.o') {
+    $bin = 'build/kernel.o';
+} else {
+    die "backtrace: can't find binary for backtrace (use --help for help)\n";
+}
+
+# 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;
 }
+
+# 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);
+