Skip to content
Permalink
1979f3c1ad
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
237 lines (221 sloc) 6.3 KB
#! @PERL@
eval "exec @PERL@ -S $0 $@"
if 0;
# Copyright (C) 1997-2016 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributed by Ulrich Drepper <drepper@gnu.org>, 1997.
# Based on the mtrace.awk script.
# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# The GNU C Library 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 GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with the GNU C Library; if not, see
# <http://www.gnu.org/licenses/>.
$VERSION = "@VERSION@";
$PKGVERSION = "@PKGVERSION@";
$REPORT_BUGS_TO = '@REPORT_BUGS_TO@';
$progname = $0;
sub usage {
print "Usage: mtrace [OPTION]... [Binary] MtraceData\n";
print " --help print this help, then exit\n";
print " --version print version number, then exit\n";
print "\n";
print "For bug reporting instructions, please see:\n";
print "$REPORT_BUGS_TO.\n";
exit 0;
}
# We expect two arguments:
# #1: the complete path to the binary
# #2: the mtrace data filename
# The usual options are also recognized.
arglist: while (@ARGV) {
if ($ARGV[0] eq "--v" || $ARGV[0] eq "--ve" || $ARGV[0] eq "--ver" ||
$ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" ||
$ARGV[0] eq "--versio" || $ARGV[0] eq "--version") {
print "mtrace $PKGVERSION$VERSION\n";
print "Copyright (C) 2016 Free Software Foundation, Inc.\n";
print "This is free software; see the source for copying conditions. There is NO\n";
print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
print "Written by Ulrich Drepper <drepper\@gnu.org>\n";
exit 0;
} elsif ($ARGV[0] eq "--h" || $ARGV[0] eq "--he" || $ARGV[0] eq "--hel" ||
$ARGV[0] eq "--help") {
&usage;
} elsif ($ARGV[0] =~ /^-/) {
print "$progname: unrecognized option `$ARGV[0]'\n";
print "Try `$progname --help' for more information.\n";
exit 1;
} else {
last arglist;
}
}
if ($#ARGV == 0) {
$binary="";
$data=$ARGV[0];
} elsif ($#ARGV == 1) {
$binary=$ARGV[0];
$data=$ARGV[1];
if ($binary =~ /^.*[\/].*$/) {
$prog = $binary;
} else {
$prog = "./$binary";
}
if (open (LOCS, "env LD_TRACE_LOADED_OBJECTS=1 $prog |")) {
while (<LOCS>) {
chop;
if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) {
$locs{$1} = $2;
}
}
close (LOCS);
}
} else {
die "Wrong number of arguments, run $progname --help for help.";
}
sub location {
my $str = pop(@_);
return $str if ($str eq "");
if ($str =~ /.*[[](0x[^]]*)]:(.)*/) {
my $addr = $1;
my $fct = $2;
return $cache{$addr} if (exists $cache{$addr});
if ($binary ne "" && open (ADDR, "addr2line -e $binary $addr|")) {
my $line = <ADDR>;
chomp $line;
close (ADDR);
if ($line ne '??:0') {
$cache{$addr} = $line;
return $cache{$addr};
}
}
$cache{$addr} = $str = "$fct @ $addr";
} elsif ($str =~ /^(.*):.*[[](0x[^]]*)]$/) {
my $prog = $1;
my $addr = $2;
my $searchaddr;
return $cache{$addr} if (exists $cache{$addr});
if ($locs{$prog} ne "") {
$searchaddr = sprintf "%#x", $addr - $locs{$prog};
} else {
$searchaddr = $addr;
$prog = $binary;
}
if ($binary ne "" && open (ADDR, "addr2line -e $prog $searchaddr|")) {
my $line = <ADDR>;
chomp $line;
close (ADDR);
if ($line ne '??:0') {
$cache{$addr} = $line;
return $cache{$addr};
}
}
$cache{$addr} = $str = $addr;
} elsif ($str =~ /^.*[[](0x[^]]*)]$/) {
my $addr = $1;
return $cache{$addr} if (exists $cache{$addr});
if ($binary ne "" && open (ADDR, "addr2line -e $binary $addr|")) {
my $line = <ADDR>;
chomp $line;
close (ADDR);
if ($line ne '??:0') {
$cache{$addr} = $line;
return $cache{$addr};
}
}
$cache{$addr} = $str = $addr;
}
return $str;
}
$nr=0;
open(DATA, "<$data") || die "Cannot open mtrace data file";
while (<DATA>) {
my @cols = split (' ');
my $n, $where;
if ($cols[0] eq "@") {
# We have address and/or function name.
$where=$cols[1];
$n=2;
} else {
$where="";
$n=0;
}
$allocaddr=$cols[$n + 1];
$howmuch=hex($cols[$n + 2]);
++$nr;
SWITCH: {
if ($cols[$n] eq "+") {
if (defined $allocated{$allocaddr}) {
printf ("+ %#0@XXX@x Alloc %d duplicate: %s %s\n",
hex($allocaddr), $nr, &location($addrwas{$allocaddr}),
$where);
} elsif ($allocaddr =~ /^0x/) {
$allocated{$allocaddr}=$howmuch;
$addrwas{$allocaddr}=$where;
}
last SWITCH;
}
if ($cols[$n] eq "-") {
if (defined $allocated{$allocaddr}) {
undef $allocated{$allocaddr};
undef $addrwas{$allocaddr};
} else {
printf ("- %#0@XXX@x Free %d was never alloc'd %s\n",
hex($allocaddr), $nr, &location($where));
}
last SWITCH;
}
if ($cols[$n] eq "<") {
if (defined $allocated{$allocaddr}) {
undef $allocated{$allocaddr};
undef $addrwas{$allocaddr};
} else {
printf ("- %#0@XXX@x Realloc %d was never alloc'd %s\n",
hex($allocaddr), $nr, &location($where));
}
last SWITCH;
}
if ($cols[$n] eq ">") {
if (defined $allocated{$allocaddr}) {
printf ("+ %#0@XXX@x Realloc %d duplicate: %#010x %s %s\n",
hex($allocaddr), $nr, $allocated{$allocaddr},
&location($addrwas{$allocaddr}), &location($where));
} else {
$allocated{$allocaddr}=$howmuch;
$addrwas{$allocaddr}=$where;
}
last SWITCH;
}
if ($cols[$n] eq "=") {
# Ignore "= Start".
last SWITCH;
}
if ($cols[$n] eq "!") {
# Ignore failed realloc for now.
last SWITCH;
}
}
}
close (DATA);
# Now print all remaining entries.
@addrs= keys %allocated;
$anything=0;
if ($#addrs >= 0) {
foreach $addr (sort @addrs) {
if (defined $allocated{$addr}) {
if ($anything == 0) {
print "\nMemory not freed:\n-----------------\n";
print ' ' x (@XXX@ - 7), "Address Size Caller\n";
$anything=1;
}
printf ("%#0@XXX@x %#8x at %s\n", hex($addr), $allocated{$addr},
&location($addrwas{$addr}));
}
}
}
print "No memory leaks.\n" if ($anything == 0);
exit $anything != 0;