oskit/oskit-20020317/unsupported/scripts/sym-trace.in

164 lines
4.4 KiB
Perl
Executable File

#!/usr/bin/perl
## sym-trace -- Really, its -*-perl-*-.
##
## Copyright (c) 1997-2000 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;
}