129d706d77
* libio/fileops.c (_IO_new_file_fopen): Correctly locate ccs= substring. Don't handle ccs= if no descriptor was allocated. Normalize codeset name before calling __wcsmbs_named_conv. Initialize transliteration elements. Free step data structure. * libio/iofclose.c (_IO_new_fclose): Correct freeing of the step data. * libio/iofwide.c (__libio_translit): Renamed from libio_translit and made public. Various little cleanup changes. * wcsmbs/wcsmbsload.h (struct gconv_fcts): Add towc_nsteps and tomb_nsteps member. * wcsmbs/wcsmbsload.c: Add some casts to avoid warnings. (__wcsmbs_gconv_fcts): Initialize towc_nsteps and tomb_nsteps member. (getfct): Take additional parameter with pointer to variable where the number of steps is stored in. Disable code which allows to use more than one step for now. Adjust all callers. (free_mem): New function. Frees data associated with currently selected converters.
236 lines
6.3 KiB
Perl
236 lines
6.3 KiB
Perl
#! @PERL@
|
|
eval "exec @PERL@ -S $0 $*"
|
|
if 0;
|
|
# Copyright (C) 1997, 1998, 1999, 2000, 2001 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, write to the Free
|
|
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
# 02111-1307 USA.
|
|
|
|
$VERSION = "@VERSION@";
|
|
$PACKAGE = "libc";
|
|
$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 "Report bugs using the `glibcbug' script to <bugs\@gnu.org>.\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 (GNU $PACKAGE) $VERSION\n";
|
|
print "Copyright (C) 2001 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, $wherewas{$allocaddr}, $where);
|
|
} else {
|
|
$allocated{$allocaddr}=$howmuch;
|
|
$wherewas{$allocaddr}=&location($where);
|
|
}
|
|
last SWITCH;
|
|
}
|
|
if ($cols[$n] eq "-") {
|
|
if (defined $allocated{$allocaddr}) {
|
|
undef $allocated{$allocaddr};
|
|
undef $wherewas{$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 $wherewas{$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},
|
|
$wherewas{$allocaddr}, &location($where));
|
|
} else {
|
|
$allocated{$allocaddr}=$howmuch;
|
|
$wherewas{$allocaddr}=&location($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},
|
|
$wherewas{$addr});
|
|
}
|
|
}
|
|
}
|
|
print "No memory leaks.\n" if ($anything == 0);
|
|
|
|
exit $anything != 0;
|