mirror of https://github.com/dzavalishin/oskit/
164 lines
4.4 KiB
Perl
Executable File
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;
|
|
}
|