#! /usr/bin/env perl # # script to run gdb on return-addresses # Usage: $0 malloc-log-file binary # # Copyright 1995 by Gray Watson # # This file is part of the dmalloc package. # # Permission to use, copy, modify, and distribute this software for # any purpose and without fee is hereby granted, provided that the # above copyright notice and this permission notice appear in all # copies, and that the name of Gray Watson not be used in advertising # or publicity pertaining to distribution of the document or software # without specific, written prior permission. # # Gray Watson makes no representations about the suitability of the # software described herein for any purpose. It is provided "as is" # without express or implied warranty. # # The author may be contacted at gray.watson@letters.com # # $Id$ # # # Use this Perl script to run gdb and get information on the return-address # (ra) addresses from a dmalloc logfile output. This will search for # any ra= lines and will examine them and try to get the line number. # # NOTE: you may want to direct the output from the script to a file # else gdb seems to prompt for a return like you are on the end of a # page. # # Be sure to send me mail if there is an easier way to do all this. # ############################################################################### # usage message # if (@ARGV != 2 ) { die "Usage: $0 dmalloc-log binary-that-generated-log\n"; } $malloc = @ARGV[0]; $command = @ARGV[1]; @addresses = (); open(malloc, $malloc); while ( ) { if ($_ =~ m/ra=(0x[0-9a-fA-F]+)/) { push(@addresses, $1); } } close(malloc); open(SORT, "|sort -u > $malloc.tmp"); foreach $address (@addresses) { print SORT "$address\n"; } close(SORT); @addresses = (); open(SORT, "< $malloc.tmp"); while ( ) { chomp $_; push(@addresses, $_); } close(SORT); unlink $malloc.tmp; open (gdb, "|gdb -nx -q $command > $malloc.tmp") || die "Could not run gdb: $!\n"; $| = 1; # get rid of the (gdb) printf (gdb "set prompt\n"); printf (gdb "echo \\n\n"); # load in the shared libraries printf (gdb "sharedlibrary\n"); # run the program to have _definitly_ the informations # we need from the shared libraries. Unfortunatly gdb 4.18's # version of sharedlibrary does nothing ;( printf (gdb "b main\n"); printf (gdb "run\n"); foreach $address (@addresses) { printf (gdb "echo -----------------------------------------------\\n\n"); # printf (gdb "echo Address = '%s'\n", $address); printf (gdb "x %s\n", $address); printf (gdb "info line *(%s)\n", $address); } printf (gdb "quit\ny\n"); # $| = 0; close(gdb); %lines = (); open(malloc, "< $malloc.tmp"); $count = 0; $address = ""; $line = ""; while ( ) { # ignore our own input if ($_ =~ m/^x 0x/ || $_ =~ m/^echo ------/ || $_ =~ m/^info line/) { next; } if ($_ =~ m/^--------/) { if ($line) { $lines{$address} = "$line"; } $count = 0; $address = ""; $line = ""; } else { $count = $count + 1; } if ($count == 1 && $_ =~ m/(0x[0-9a-fA-F]+)\s*<(.*)>:\s*(\S+)/) { $address = $1; $line = "$2<$3>"; } if ($count == 2 && $_ =~ m/Line ([0-9]+) of \"([^\"]*)\"/) { $line = "$2:$1"; } } if ($line) { $lines{$address} = "$line"; } close(malloc); open(malloc, $malloc); while ( ) { if ($_ =~ m/ra=(0x[0-9a-fA-F]+)/) { $address = $1; if (defined($lines{$address})) { $_ =~ s/ra=$address/$lines{$address}/; print STDOUT $_; } else { print STDOUT $_; } } else { print STDOUT $_; } }