Welcome callygraphs.sh
Signed-off-by: hax <hax@lainlounge.xyz>
This commit is contained in:
parent
05f7ac2f2d
commit
e33a82abae
1 changed files with 126 additions and 0 deletions
126
callygraphs.sh
Normal file
126
callygraphs.sh
Normal file
|
@ -0,0 +1,126 @@
|
|||
#! /usr/bin/env bash
|
||||
# Reserved for future comments ...
|
||||
#
|
||||
#
|
||||
#
|
||||
# --------------------------------
|
||||
|
||||
prog_name="callygraphs"
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "Usage: $prog_name EXECUTABLE [ARGS...]"
|
||||
echo
|
||||
echo "Example: $prog_name ~/bin/test-program foo 23"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Sanity checks.
|
||||
FILE=$1
|
||||
|
||||
if [ ! -x $FILE ]; then
|
||||
echo "$prog_name: Unable to find executable '$FILE'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LANG="" gdb --eval-command=quit $FILE 2>&1 \
|
||||
| grep -E '(no\ debugging\ symbols\ found|not\ in\ executable\ format)' 2>&1 > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -n "$prog_name: Can't print call graph for '$FILE' because it's not a "
|
||||
echo "binary executable compiled with debugging symbols."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
# Set up temporary files.
|
||||
TRACE="`mktemp -t $prog_name.XXXXXXXXXX`" || exit
|
||||
GETFUNCS="`mktemp -t $prog_name.XXXXXXXXXX`" || exit
|
||||
trap 'rm -f -- "$TRACE" "$GETFUNCS"' EXIT
|
||||
trap 'trap - EXIT; rm -f -- "$TRACE" "$GETFUNCS"; exit 1' HUP INT QUIT TERM
|
||||
|
||||
# Take control of GDB and print call graph.
|
||||
cat > $GETFUNCS <<EOF
|
||||
set height 0
|
||||
info functions
|
||||
EOF
|
||||
|
||||
gdb --batch --command=$GETFUNCS $FILE 2>/dev/null | awk '
|
||||
function get_func_name(str)
|
||||
{
|
||||
split(str, part, "(");
|
||||
len = split(part[1], part, " ");
|
||||
len = split(part[len], part, "*");
|
||||
|
||||
return part[len];
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
total = 0;
|
||||
print "set width 0";
|
||||
print "set height 0";
|
||||
print "set verbose off";
|
||||
}
|
||||
|
||||
/[a-zA-Z_][a-zA-Z0-9_]*\(/ {
|
||||
fn = get_func_name($0);
|
||||
printf("break %s\n", fn);
|
||||
++total;
|
||||
}
|
||||
|
||||
END {
|
||||
for (i = 1; i <= total; i++) {
|
||||
print "commands", i;
|
||||
/* print "info args"; */
|
||||
print "backtrace 2";
|
||||
print "continue";
|
||||
print "end";
|
||||
}
|
||||
|
||||
print "run"
|
||||
}
|
||||
' > $TRACE
|
||||
|
||||
gdb --batch --command=$TRACE --tty=/dev/null --args $FILE $@ 2>/dev/null | awk '
|
||||
function get_callee(s)
|
||||
{
|
||||
split(s, info, ",");
|
||||
split(info[2], fn, " ");
|
||||
callee = fn[1];
|
||||
|
||||
return callee;
|
||||
}
|
||||
|
||||
function get_params(s, n)
|
||||
{
|
||||
split(s, par, n);
|
||||
split(par[2], par, " at ");
|
||||
sub(/ \(/, "(", par[1]);
|
||||
|
||||
return par[1];
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
isrecord = 0;
|
||||
callee = "";
|
||||
caller = "*INITIAL*";
|
||||
params = "";
|
||||
}
|
||||
|
||||
/^Breakpoint [0-9]+,/ {
|
||||
isrecord = 1;
|
||||
|
||||
callee = get_callee($0);
|
||||
params = get_params($0, callee);
|
||||
}
|
||||
|
||||
/^#1[ \t]+/ {
|
||||
if (isrecord)
|
||||
caller = $4;
|
||||
}
|
||||
|
||||
/^$/ {
|
||||
if (isrecord && (caller != "*INITIAL*")) {
|
||||
printf("%s %s %s\n", caller, callee, params);
|
||||
callee = caller = params = "";
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue