Skip to content

Instantly share code, notes, and snippets.

@debedb
Created December 1, 2014 18:31
Show Gist options
  • Save debedb/2b00c6c5de1a0c21da7f to your computer and use it in GitHub Desktop.
Save debedb/2b00c6c5de1a0c21da7f to your computer and use it in GitHub Desktop.
Print call sequence of a C program
#!/usr/bin/perl
# See http://debedb.blogspot.com/2007/02/poor-mans-tracepoints-and-call-sequence.html
use FileHandle;
use IPC::Open2;
if (! (-e "tags")) {
print "Cannot find tags, will run\n";
$tagCmd = "ctags *.h *.c";
print "\t$tagCmd\n";
system($tagCmd) && die ("Make sure ctags is installed\n");
}
%breakId2Func = {};
%func2Args = {};
#if ($ARGV[0] eq "prepare") {
# exec('ctags *.h *.c');
$exec = $ARGV[0];
splice(@ARGV, 0, 1);
$pid = open2(*Reader, *Writer, "gdb -annotate 3 --interpreter=mi $exec");
while (<Reader>) {
chop;
last if ($_ eq "(gdb) ")
}
print Writer "set print pretty on\n";
while (<Reader>) {
chop;
last if ($_ eq "(gdb) ")
}
print Writer "set print array on\n";
while (<Reader>) {
chop;
last if ($_ eq "(gdb) ")
}
print Writer "set print union on\n";
while (<Reader>) {
chop;
last if ($_ eq "(gdb) ")
}
print "...\n";
open(GREP, 'grep "f$" ./tags|') || die "Do you have ctags?\n";
while (<GREP>) {
($func, $file, $regexp, $f) = split(/\t+/);
$from = index($regexp, "(") + 1;
$to = rindex($regexp, ")");
$args = substr($regexp, $from, $to - $from);
print Writer "break $func\n";
while (<Reader>) {
# Store the number of the breakpoint, we will
# need it later to determine when it's hit
chop;
if ($_ =~ /Breakpoint/) {
$breakId = substr($_, length('~"Breakpoint '));
$breakId = substr($breakId, 0, index($breakId, " "));
$breakId2Func{$breakId} = $func;
}
last if $_ eq "(gdb) ";
}
##############################################################
# I wrote this when I didn't realize I can call "info args"
# But maybe saving this is still useful for more information
# like figuring out the type of variable and printing more
# info about it, in case it's some pointer to struct to whatever
#
# Save argument names for evaluation when breakpoint is hit
# @args = split(/,/, $args );
#
# @$func = ();
# foreach $arg (@args) {
# @typeAndVar = split(/\s+/,$arg);
#
# $$func[++$#$func] = $typeAndVar[$#typeAndVar];
# }
# $func2Args{$func} = \@$func;
# *x = $func2Args{$func};
# print "$func > @x\n";
# }
print "Calling run @ARGV\n";
print Writer "run @ARGV\n";
$inBreak = 0;
while (<Reader>) {
chop;
if ($_ =~ /Breakpoint/) {
# print "$_\n";
$breakId = substr($_, length('~"Breakpoint '));
$breakId = substr($breakId, 0, index($breakId, ","));
$func = $breakId2Func{$breakId};
$inBreak = $breakId;
# Which one is better?
print Writer "info args\n";
# print Writer "-stack-list-arguments 1 0 0\n";
print Writer "cont\n";
}
if ($inBreak) {
if ($_ =~ /~\"Continuing./) {
$inBreak = 0;
print "***************************\n";
} else {
if ($_ ne "(gdb) " &&
$_ ne "^done" &&
$_ ne '~"\n"' &&
$_ ne '&"cont\n"' &&
$_ !~ /stopped/) {
$_ =~ s/\\[nt]//g;
$_ =~ s/\\032//g;
$_ =~ s/^~\"//g;
print "$_\n";
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment