1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
#!/usr/bin/perl
## sym-trace -- Really, its -*-perl-*-.
##
## Copyright (c) 1997-1999 University of Utah and the Flux Group.
## All rights reserved.
##
## This file is part of the Flux OSKit. The OSKit is free software, also known
## as "open source;" you can redistribute it and/or modify it under the terms
## of the GNU General Public License (GPL), version 2, as published by the Free
## Software Foundation (FSF). To explore alternate licensing terms, contact
## the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
##
## The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
## received a copy of the GPL along with the OSKit; see the file COPYING. If
## not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
##
##
## Turn a stack trace into a list of function names.
##
## Expects a list in the format that backtrace() dumps it.
## By default looks at obj/kernel/fluke. You may want
## something different and should use the "-o <obj>" option
## to specifiy a different object/executable. Or, set the
## env var FLSYM_TARGET to the name of the object file.
##
## This script is tweaked and customized for the envronment here
## at the University of Utah. It is not a supported part of
## of the OSKit release (Tech Support just won't know what you're
## talking about.) You will have to customize it somewhat for
## your environment.
##
open(HOSTNAME_HACK, "hostname|") || die "Can't exec 'hostname'\n";
$hostname = <HOSTNAME_HACK>;
chop $hostname;
close(HOSTNAME_HACK);
#default object file
$objectFile = $ENV{'FLSYM_TARGET'};
$objectFile = "obj/kernel/fluke" if ( "$objectFile" eq "" ) ;
## This gets replaced by configure.
$nm = @NM@
if ($hostname eq "marker.cs.utah.edu") {
$nm = "/usr/local/fluke/bin/i486-linux-nm";
} elsif ($hostname eq "fast.cs.utah.edu") {
$nm = "/n/fast/usr/lsrc/mach/tools/i486-linux/bin/nm";
}
## Parse the command line arguments
$inputFormat = 1; # default format
while (@ARGV) {
## -o <objectfile> to use a different object file
if ($ARGV[0] eq "-o") {
if ($#ARGV >= 1) {
$objectFile = $ARGV[1];
shift @ARGV;
} else {
&usage;
}
##
} elsif ($ARGV[0] eq "-oneline") {
$inputFormat = 1;
} elsif ($ARGV[0] eq "-perline") {
$inputFormat = 0;
## -h for usage
} elsif ($ARGV[0] eq "-h") {
&usage;
## Unknown args are fatal
} else {
print "Unknown option $ARGV[0]\n";
&usage;
}
shift @ARGV;
}
-x $objectFile || die "$objectFile not found.\n";
## yes this is bad.. just stick the whole output into
## the OBLIST array. Note that we make nm output in
## decimal, sorted by address
open (NMOUT, "$nm --numeric-sort --radix=d $objectFile|");
@OBLIST = <NMOUT>;
@BACKTRACE = <STDIN>;
@BACKTRACE || die "No stdin provided??\n";
$ct = 0;
print "Generating backtrace for object file $objectFile\n";
while (@BACKTRACE) {
$traceLine = shift @BACKTRACE;
chop $traceLine;
next if ($traceLine eq "");
if ($inputFormat == 0) {
# If old, eip-per-line format
($bs, $eipStr) = split(/=/, $traceLine, 2);
$eip = oct($eipStr); # Cvt from 0xNNN notation to _decimal_
&findFunction($eip);
} else {
# Else, the one line of eips format
@eips = split(' ', $traceLine);
foreach $eip (@eips) {
$eipDec = oct("0x" . "$eip");# Cvt from hex NNN notation to _decimal_
&findFunction($eipDec);
}
}
}
#
# Given an EIP, find the name of the corresponding function
# (EIP should be in decimal)
sub findFunction {
local($eip) = @_;
local($more, $index, $bestAddr, $bestFunc, $addr, $type, $proc);
$more = 1;
$index = 0;
$bestAddr = -1;
$bestFunc = "NOT FOUND";
while ($more && $eip && ($index <= $#OBLIST)) {
$_ = $OBLIST[$index];
chop;
($addr, $type, $proc) = split(/ /, $_, 3);
# List is sorted, so if we go beyond, then prev is answer.
if ($addr > $eip) {
$more = 0;
}
else
{
$bestFunc = $proc;
$bestAddr = $addr;
$index += 1;
}
}
# If we didn't find a useful address...
if ($index > $#OBLIST) {
$bestFunc = "<Not Found>";
$bestAddr = 0;
}
if ($eip) {
printf "0x%07x in (0x%07x) $bestFunc()\n", $eip, $bestAddr;
}
}
sub usage
{
print "sym-trace [-o <objectfile>] [-perline] [-oneline] [-h]\n";
exit 0;
}
|