Make tests public. Rewrite most tests. Add tests.
[pintos-anon] / src / utils / backtrace
1 #! /usr/bin/perl -w
2
3 use strict;
4
5 # Check command line.
6 if (grep ($_ eq '-h' || $_ eq '--help', @ARGV)) {
7     print <<'EOF';
8 backtrace, for converting raw addresses into symbolic backtraces
9 usage: backtrace [BINARY] ADDRESS...
10 where BINARY is the binary file from which to obtain symbols
11  and ADDRESS is a raw address to convert to a symbol name.
12
13 If BINARY is unspecified, the default is the first of kernel.o or
14 build/kernel.o that exists.
15
16 The ADDRESS list should be taken from the "Call stack:" printed by the
17 kernel.  Read "Backtraces" in the "Debugging Tools" chapter of the
18 Pintos documentation for more information.
19 EOF
20     exit 0;
21 }
22 die "backtrace: at least one argument required (use --help for help)\n"
23     if @ARGV == 0;
24
25 # Drop leading and trailing garbage inserted by kernel.
26 shift while grep (/^(call|stack:?)$/i, $ARGV[0]);
27 s/\.$// foreach @ARGV;
28
29 # Find binary file.
30 my ($bin) = $ARGV[0];
31 if (-e $bin) {
32     shift @ARGV;
33 } elsif ($bin !~ /^0/) {
34     die "backtrace: $bin: not found (use --help for help)\n";
35 } elsif (-e 'kernel.o') {
36     $bin = 'kernel.o';
37 } elsif (-e 'build/kernel.o') {
38     $bin = 'build/kernel.o';
39 } else {
40     die "backtrace: can't find binary for backtrace (use --help for help)\n";
41 }
42
43 # Find addr2line.
44 my ($a2l) = search_path ("i386-elf-addr2line") || search_path ("addr2line");
45 if (!$a2l) {
46     die "backtrace: neither `i386-elf-addr2line' nor `addr2line' in PATH\n";
47 }
48 sub search_path {
49     my ($target) = @_;
50     for my $dir (split (':', $ENV{PATH})) {
51         my ($file) = "$dir/$target";
52         return $file if -e $file;
53     }
54     return undef;
55 }
56
57 # Do backtrace.
58 open (A2L, "$a2l -fe $bin " . join (' ', @ARGV) . "|");
59 while (<A2L>) {
60     my ($function, $line);
61     chomp ($function = $_);
62     chomp ($line = <A2L>);
63     print shift (@ARGV), ": $function ($line)\n";
64 }
65 close (A2L);
66