--- mtrace 2010-08-26 14:51:00.148982905 +0530 +++ mt-helper 2010-08-26 14:50:29.668982236 +0530 @@ -21,6 +21,7 @@ # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. + $VERSION = "2.10.1"; $PKGVERSION = "(EGLIBC) "; $REPORT_BUGS_TO = ''; @@ -50,7 +51,7 @@ 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 \n"; - + exit 0; } elsif ($ARGV[0] eq "--h" || $ARGV[0] eq "--he" || $ARGV[0] eq "--hel" || $ARGV[0] eq "--help") { @@ -64,175 +65,352 @@ } } -if ($#ARGV == 0) { +if ($#ARGV == 0) +{ $binary=""; $data=$ARGV[0]; -} elsif ($#ARGV == 1) { +} +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 () { - chop; - if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) { - $locs{$1} = $2; - } - } - close (LOCS); - } -} else { + if ($binary =~ /^.*[\/].*$/) + { + $prog = $binary; + } + else + { + $prog = "./$binary"; + } + if (open (LOCS, "env LD_TRACE_LOADED_OBJECTS=1 $prog |")) + { + while () + { + chop; + if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) + { + $locs{$1} = $2; + } + } + close (LOCS); + } +} +else +{ die "Wrong number of arguments, run $progname --help for help."; } -sub location { +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 = ; - 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 = ; - 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 = ; - chomp $line; - close (ADDR); - if ($line ne '??:0') { - $cache{$addr} = $line; - return $cache{$addr}; - } - } - $cache{$addr} = $str = $addr; + 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 = ; + 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 = ; + 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 = ; + chomp $line; + close (ADDR); + if ($line ne '??:0') + { + $cache{$addr} = $line; + return $cache{$addr}; + } + } + $cache{$addr} = $str = $addr; } return $str; } +sub mmapparser +{ + my $name = $_[1]; + my $addr_hex = $_[0]; + return $name if ($name eq ""); + my $l=$name; + $addr_hex =~ /^(.*):.*[[](0x[^]]*)]$/; + $addr_hex=$2; + my $addr_dec = hex($addr_hex); + my $file="./mmapinfo.log"; + my $offset_addr=0; + my $tmp; + + if (-e "$file") + { + open (MMAPFILE,"$file"); + + while($tmp = ) + { + @words = split / /,$tmp; + @addresses = split /-/,$words[0]; + + $a0_hex=$addresses[0]; + $a0_dec=hex($a0_hex); + + $a1_hex=$addresses[1]; + $a1_dec=hex($a1_hex); + + if ($addr_dec>=$a0_dec and $addr_dec<=$a1_dec) + { + $offset_addr=$addr_dec-$a0_dec; + $offset_addr=sprintf("%x", $offset_addr); + last; + } + } + + close (MMAPFILE); + open (ADDR1, "addr2line -e $name $offset_addr|"); + $line = ; + chomp $line; + close (ADDR1); + if ( $line ne '??:0') + { + return $line; + } + else + { + return $l; + } + + + + } + else + { + #die "**mtrace** ERROR: $file not found. Aborting. \n"; + #Currently script does nothing. The output will contain the leaks occurring in + #DSOs but without the location info. + } +} + $nr=0; open(DATA, "<$data") || die "Cannot open mtrace data file"; -while () { +while () +{ 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; + if ($cols[0] eq "@") + { + # We have address and/or function name. + $where=$cols[1]; + $n=2; + $temp = $where; + } + else + { + $where=""; + $n=0; } + undef $libname; + if ($temp =~ m/^(.*so.*):.*/) + { + $lib = $1; + if ($lib =~ m/^.*lib.*so.*/) + { + $libname=$lib; + } + + } $allocaddr=$cols[$n + 1]; $howmuch=hex($cols[$n + 2]); - ++$nr; - SWITCH: { - if ($cols[$n] eq "+") { - if (defined $allocated{$allocaddr}) { - printf ("+ %#010x Alloc %d duplicate: %s %s\n", - hex($allocaddr), $nr, &location($addrwas{$allocaddr}), - $where); - } else { - $allocated{$allocaddr}=$howmuch; - $addrwas{$allocaddr}=$where; - } - last SWITCH; - } - if ($cols[$n] eq "-") { - if (defined $allocated{$allocaddr}) { - undef $allocated{$allocaddr}; - undef $addrwas{$allocaddr}; - } else { - printf ("- %#010x 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 ("- %#010x Realloc %d was never alloc'd %s\n", - hex($allocaddr), $nr, &location($where)); - } - last SWITCH; - } - if ($cols[$n] eq ">") { - if (defined $allocated{$allocaddr}) { - printf ("+ %#010x 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; - } + SWITCH: + { + if ($cols[$n] eq "+") + { + if (defined $allocated{$allocaddr}) + { + if (defined $libs{$allocaddr}) + { + printf ("+ %#010x Alloc %d duplicate: %s %s\n", hex($allocaddr), $nr, &mmapparser($addrwas{$allocaddr}, $libs{$allocaddr}), $where); + } + else + { + printf ("+ %#010x Alloc %d duplicate: %s %s\n", hex($allocaddr), $nr, &location($addrwas{$allocaddr}), $where); + } + } + else + { + $allocated{$allocaddr}=$howmuch; + $addrwas{$allocaddr}=$where; + if (defined $libname) + { + $libs{$allocaddr}=$libname; + } + } + last SWITCH; + } + if ($cols[$n] eq "-") + { + if (defined $allocated{$allocaddr}) + { + undef $allocated{$allocaddr}; + undef $addrwas{$allocaddr}; + if (defined $libs{$allocaddr}) + { + undef $libs{$allocaddr}; + } + } + else + { + if (defined $libs{$allocaddr}) + { + printf ("- %#010x Free %d was never alloc'd %s\n", + hex($allocaddr), $nr, &mmapparser($addrwas{$allocaddr}, $libs{$allocaddr})); + } + else + { + printf ("- %#010x 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}; + undef $libs{$allocaddr}; + } + else + { + if (defined $libs{$allocaddr}) + { + printf ("- %#010x Realloc %d was never alloc'd %s\n", + hex($allocaddr), $nr, &mmapparser($addrwas{$allocaddr}, $libs{$allocaddr})); + } + else + { + printf ("- %#010x Realloc %d was never alloc'd %s\n", + hex($allocaddr), $nr, &location($where)); + } + } + last SWITCH; + } + if ($cols[$n] eq ">") + { + if (defined $allocated{$allocaddr}) + { + if (defined $libs{$allocaddr}) + { + printf ("+ %#010x Realloc %d duplicate: %#010x %s %s\n", + hex($allocaddr), $nr, $allocated{$allocaddr}, + &mmapparser($addrwas{$allocaddr}, $libs{$allocaddr}), &location($where)); + } + else + { + printf ("+ %#010x Realloc %d duplicate: %#010x %s %s\n", + hex($allocaddr), $nr, $allocated{$allocaddr}, + &location($addrwas{$allocaddr}), &location($where)); + } + } + else + { + $allocated{$allocaddr}=$howmuch; + $addrwas{$allocaddr}=$where; + if (defined $libname) + { + $libs{$allocaddr}=$libname; + } + } + 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 (10 - 7), "Address Size Caller\n"; - $anything=1; - } - printf ("%#010x %#8x at %s\n", hex($addr), $allocated{$addr}, - &location($addrwas{$addr})); - } - } +sub hashValueDescendingNum +{ + $allocated{$b} <=> $allocated{$a}; +} + + +# Now print all remaining entries +foreach $addr (sort hashValueDescendingNum (keys(%allocated))) +{ + if (defined $allocated{$addr}) + { + if ($anything == 0) + { + print "\nMemory not freed:\n-----------------\n"; + print ' ' x (10 - 7), "Address Size Caller\n"; + $anything=1; + } + if (defined $libs{$addr}) + { + printf ("%#010x %#8x at %s\n", hex($addr), $allocated{$addr}, + &mmapparser($addrwas{$addr}, $libs{$addr})); + } + else + { + printf ("%#010x %#8x at %s\n", hex($addr), $allocated{$addr}, + &location($addrwas{$addr})); + } + } } print "No memory leaks.\n" if ($anything == 0); exit $anything != 0; +#eof