487e224791388de739f57fdd512e75b69a579fd8
[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 "backtrace, for converting raw addresses into symbolic backtraces\n";
8     print "\n";
9     print "usage: backtrace BINARY ADDRESS...\n";
10     print "where BINARY is the binary file from which to obtain symbols\n";
11     print "  and each ADDRESS is a raw address to convert to a symbol name.\n";
12     print "\n";
13     print "In use with Pintos, BINARY is usually kernel.o and the ADDRESS\n";
14     print "list is taken from the \"Call stack:\" printed by the kernel.\n";
15     print "Read \"Backtraces\" in the \"Debugging Tools\" chapter\n";
16     print "of the Pintos documentation for more information.\n";
17     exit 0;
18 }
19 die "backtrace: binary file argument required (use --help for help)\n"
20     if @ARGV == 0;
21 die "backtrace: at least one address argument required (use --help for help)\n"
22     if @ARGV == 1;
23
24 # Find binary file.
25 my ($bin) = shift @ARGV;
26 die "backtrace: $bin: not found (use --help for help)\n"
27     if ! -e $bin;
28
29 # Find addr2line.
30 my ($a2l) = search_path ("i386-elf-addr2line") || search_path ("addr2line");
31 if (!$a2l) {
32     die "backtrace: neither `i386-elf-addr2line' nor `addr2line' in PATH\n";
33 }
34 sub search_path {
35     my ($target) = @_;
36     for my $dir (split (':', $ENV{PATH})) {
37         my ($file) = "$dir/$target";
38         return $file if -e $file;
39     }
40     return undef;
41 }
42
43 # Drop leading and trailing garbage inserted by kernel.
44 shift while grep (/call|stack/i, $ARGV[0]);
45 s/\.$// foreach @ARGV;
46
47 # Do backtrace.
48 open (A2L, "$a2l -fe $bin " . join (' ', @ARGV) . "|");
49 while (<A2L>) {
50     my ($function, $line);
51     chomp ($function = $_);
52     chomp ($line = <A2L>);
53     print shift (@ARGV), ": $function ($line)\n";
54 }
55 close (A2L);
56