tools/trace-malloc/TraceMalloc.pm

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/trace-malloc/TraceMalloc.pm	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,156 @@
     1.4 +# This Source Code Form is subject to the terms of the Mozilla Public
     1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.7 +package TraceMalloc;
     1.8 +
     1.9 +use strict;
    1.10 +
    1.11 +# Read in the type inference file and construct a network that we can
    1.12 +# use to match stack prefixes to types.
    1.13 +sub init_type_inference($) {
    1.14 +    my ($file) = @_;
    1.15 +
    1.16 +    $::Fingerprints = { };
    1.17 +
    1.18 +    open(TYPES, "<$file") || die "unable to open $::opt_types, $!";
    1.19 +
    1.20 +  TYPE: while (<TYPES>) {
    1.21 +      next TYPE unless /<(.*)>/;
    1.22 +      my $type = $1;
    1.23 +
    1.24 +      my $link = \%::Fingerprints;
    1.25 +
    1.26 +    FRAME: while (<TYPES>) {
    1.27 +        chomp;
    1.28 +        last FRAME if /^$/;
    1.29 +
    1.30 +        my $next = $link->{$_};
    1.31 +        if (! $next) {
    1.32 +            $next = $link->{$_} = {};
    1.33 +        }
    1.34 +        $link = $next;
    1.35 +    }
    1.36 +
    1.37 +      $link->{'#type#'} = $type;
    1.38 +
    1.39 +      last TYPE if eof;
    1.40 +  }
    1.41 +}
    1.42 +
    1.43 +# Infer the type, trying to find the most specific type possible.
    1.44 +sub infer_type($) {
    1.45 +    my ($stack) = @_;
    1.46 +
    1.47 +    my $link = \%::Fingerprints;
    1.48 +    my $last;
    1.49 +    my $type = 'void*';
    1.50 +  FRAME: foreach my $frame (@$stack) {
    1.51 +      last FRAME unless $link;
    1.52 +
    1.53 +      $frame =~ s/\[.*\]$//; # ignore exact addresses, as they'll drift
    1.54 +
    1.55 +      $last = $link;
    1.56 +
    1.57 +      #
    1.58 +      # Remember this type, but keep going.  We use the longest match
    1.59 +      # we find, but substacks of longer matches will also match.
    1.60 +      #
    1.61 +      if ($last->{'#type#'}) {
    1.62 +          $type = $last->{'#type#'};
    1.63 +      }
    1.64 +
    1.65 +      $link = $link->{$frame};
    1.66 +
    1.67 +      if (! $link) {
    1.68 +        CHILD: foreach my $child (keys %$last) {
    1.69 +            next CHILD unless $child =~ /^~/;
    1.70 +
    1.71 +            $child =~ s/^~//;
    1.72 +
    1.73 +            if ($frame =~ $child) {
    1.74 +                $link = $last->{'~' . $child};
    1.75 +                last CHILD;
    1.76 +            }
    1.77 +          }
    1.78 +      }
    1.79 +  }
    1.80 +
    1.81 +    return $type;
    1.82 +}
    1.83 +
    1.84 +
    1.85 +#----------------------------------------------------------------------
    1.86 +#
    1.87 +# Read in the output a trace malloc's dump. 
    1.88 +#
    1.89 +sub read {
    1.90 +    my ($callback, $noslop) = @_;
    1.91 +
    1.92 +  OBJECT: while (<>) {
    1.93 +      # e.g., 0x0832FBD0 <void*> (80)
    1.94 +      next OBJECT unless /^0x(\S+) <(.*)> \((\d+)\)/;
    1.95 +      my ($addr, $type, $size) = (hex $1, $2, $3);
    1.96 +
    1.97 +      my $object = { 'type' => $type, 'size' => $size };
    1.98 +
    1.99 +      # Record the object's slots
   1.100 +      my @slots;
   1.101 +
   1.102 +    SLOT: while (<>) {
   1.103 +        # e.g.,      0x00000000
   1.104 +        last SLOT unless /^\t0x(\S+)/;
   1.105 +        my $value = hex $1;
   1.106 +
   1.107 +        # Ignore low bits, unless they've specified --noslop
   1.108 +        $value &= ~0x7 unless $noslop;
   1.109 +
   1.110 +        $slots[$#slots + 1] = $value;
   1.111 +    }
   1.112 +
   1.113 +      $object->{'slots'} = \@slots;
   1.114 +
   1.115 +      # Record the stack by which the object was allocated
   1.116 +      my @stack;
   1.117 +
   1.118 +      while (/^(.*)\[(.*) \+0x(\S+)\]$/) {
   1.119 +          # e.g., _dl_debug_message[/lib/ld-linux.so.2 +0x0000B858]
   1.120 +          my ($func, $lib, $off) = ($1, $2, hex $3);
   1.121 +
   1.122 +          chomp;
   1.123 +          $stack[$#stack + 1] = $_;
   1.124 +
   1.125 +          $_ = <>;
   1.126 +      }
   1.127 +
   1.128 +      $object->{'stack'} = \@stack;
   1.129 +
   1.130 +      $object->{'type'} = infer_type(\@stack)
   1.131 +          if $object->{'type'} eq 'void*';
   1.132 +
   1.133 +      &$callback($object) if $callback;
   1.134 +
   1.135 +      # Gotta check EOF explicitly...
   1.136 +      last OBJECT if eof;
   1.137 +  }
   1.138 +}
   1.139 +
   1.140 +1;
   1.141 +__END__
   1.142 +
   1.143 +=head1 NAME
   1.144 +
   1.145 +TraceMalloc - Perl routines to deal with output from ``trace malloc''
   1.146 +and the Boehm GC
   1.147 +
   1.148 +=head1 SYNOPSIS
   1.149 +
   1.150 +    use TraceMalloc;
   1.151 +
   1.152 +    TraceMalloc::init_type_inference("types.dat");
   1.153 +    TraceMalloc::read(0);
   1.154 +
   1.155 +=head1 DESCRIPTION
   1.156 +
   1.157 +=head1 EXAMPLES
   1.158 +
   1.159 +=cut

mercurial