#! /usr/bin/perl sub addr2line; $list = shift; $bin = shift; $ofs = shift; die "usage: mci data_file binary\n" unless -f($list); open F, $list; while() { if(/^;\s*(.+?)\s*$/) { @i = split ' ', $1; $i[0] = sprintf "%-24s", $i[0]; $i[1] = addr2line $i[1]; print "; ", join("\t", @i), "\n"; next } @i = split; die "oops, format error" if @i > 3; if(@i == 1) { if($i[0] =~ /^>(\S+)/) { unshift @funcs, $1; } elsif($i[0] =~ /<(\S+)/) { if($funcs[0] eq $1) { shift @funcs } else { die "oops, strange data (line $.)\n" } } else { die "oops, format error" } } else { $func = $i[0]; $addr = $i[1]; $size = undef; $size = @i == 2 ? undef : $i[2]; if(defined $size) { if(exists $mem{$addr}) { $x = addr2line $func; $y = addr2line ${$mem{$addr}}[1]; print "malloc oops (line $.): mem $addr; old: $y, size ${$mem{$addr}}[0]; new: $x, size $size\n"; } $mem{$addr} = [ $size, $func, @funcs ]; delete $lfree{$addr}; } else { if(!exists $mem{$addr}) { $xx = ""; $first = 1; for $f ($func, @funcs) { $xx .= "<-" unless $first; $first = 0; $xx .= addr2line $f; } print "free oops (line $.): $addr ($xx) [last free: line $lfree{$addr}]\n"; } delete $mem{$addr}; $lfree{$addr} .= " $."; } } } for (sort keys %mem) { $total += oct(${$mem{$_}}[0]); $cnt++; # $x = `addr2line -s -e $bin ${$mem{$_}}[1]`; # chomp $x; # $x = $x =~ /\?{2}/ ? undef : "$x "; $x = addr2line ${$mem{$_}}[1]; print "$_\t${$mem{$_}}[0]\t"; $first = 1; for $f (@{$mem{$_}}[1..$#{$mem{$_}}]) { print "<-" unless $first; $first = 0; print addr2line $f; } print "\n" } printf "total: %u bytes in %u blocks\n", $total, $cnt; sub addr2line { my ($x, $y); return $_[0] unless $bin; $y = sprintf "0x%x", oct($_[0]) + $ofs; return $addr_cache{$y} if exists $addr_cache{$y}; $x = `addr2line -s -e $bin $y`; chomp $x; $x = $x =~ /\?{2}/ ? $_[0] : $x; $addr_cache{$y} = $x; return $x; }