tools/trace-malloc/TraceMalloc.pm

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4 package TraceMalloc;
michael@0 5
michael@0 6 use strict;
michael@0 7
michael@0 8 # Read in the type inference file and construct a network that we can
michael@0 9 # use to match stack prefixes to types.
michael@0 10 sub init_type_inference($) {
michael@0 11 my ($file) = @_;
michael@0 12
michael@0 13 $::Fingerprints = { };
michael@0 14
michael@0 15 open(TYPES, "<$file") || die "unable to open $::opt_types, $!";
michael@0 16
michael@0 17 TYPE: while (<TYPES>) {
michael@0 18 next TYPE unless /<(.*)>/;
michael@0 19 my $type = $1;
michael@0 20
michael@0 21 my $link = \%::Fingerprints;
michael@0 22
michael@0 23 FRAME: while (<TYPES>) {
michael@0 24 chomp;
michael@0 25 last FRAME if /^$/;
michael@0 26
michael@0 27 my $next = $link->{$_};
michael@0 28 if (! $next) {
michael@0 29 $next = $link->{$_} = {};
michael@0 30 }
michael@0 31 $link = $next;
michael@0 32 }
michael@0 33
michael@0 34 $link->{'#type#'} = $type;
michael@0 35
michael@0 36 last TYPE if eof;
michael@0 37 }
michael@0 38 }
michael@0 39
michael@0 40 # Infer the type, trying to find the most specific type possible.
michael@0 41 sub infer_type($) {
michael@0 42 my ($stack) = @_;
michael@0 43
michael@0 44 my $link = \%::Fingerprints;
michael@0 45 my $last;
michael@0 46 my $type = 'void*';
michael@0 47 FRAME: foreach my $frame (@$stack) {
michael@0 48 last FRAME unless $link;
michael@0 49
michael@0 50 $frame =~ s/\[.*\]$//; # ignore exact addresses, as they'll drift
michael@0 51
michael@0 52 $last = $link;
michael@0 53
michael@0 54 #
michael@0 55 # Remember this type, but keep going. We use the longest match
michael@0 56 # we find, but substacks of longer matches will also match.
michael@0 57 #
michael@0 58 if ($last->{'#type#'}) {
michael@0 59 $type = $last->{'#type#'};
michael@0 60 }
michael@0 61
michael@0 62 $link = $link->{$frame};
michael@0 63
michael@0 64 if (! $link) {
michael@0 65 CHILD: foreach my $child (keys %$last) {
michael@0 66 next CHILD unless $child =~ /^~/;
michael@0 67
michael@0 68 $child =~ s/^~//;
michael@0 69
michael@0 70 if ($frame =~ $child) {
michael@0 71 $link = $last->{'~' . $child};
michael@0 72 last CHILD;
michael@0 73 }
michael@0 74 }
michael@0 75 }
michael@0 76 }
michael@0 77
michael@0 78 return $type;
michael@0 79 }
michael@0 80
michael@0 81
michael@0 82 #----------------------------------------------------------------------
michael@0 83 #
michael@0 84 # Read in the output a trace malloc's dump.
michael@0 85 #
michael@0 86 sub read {
michael@0 87 my ($callback, $noslop) = @_;
michael@0 88
michael@0 89 OBJECT: while (<>) {
michael@0 90 # e.g., 0x0832FBD0 <void*> (80)
michael@0 91 next OBJECT unless /^0x(\S+) <(.*)> \((\d+)\)/;
michael@0 92 my ($addr, $type, $size) = (hex $1, $2, $3);
michael@0 93
michael@0 94 my $object = { 'type' => $type, 'size' => $size };
michael@0 95
michael@0 96 # Record the object's slots
michael@0 97 my @slots;
michael@0 98
michael@0 99 SLOT: while (<>) {
michael@0 100 # e.g., 0x00000000
michael@0 101 last SLOT unless /^\t0x(\S+)/;
michael@0 102 my $value = hex $1;
michael@0 103
michael@0 104 # Ignore low bits, unless they've specified --noslop
michael@0 105 $value &= ~0x7 unless $noslop;
michael@0 106
michael@0 107 $slots[$#slots + 1] = $value;
michael@0 108 }
michael@0 109
michael@0 110 $object->{'slots'} = \@slots;
michael@0 111
michael@0 112 # Record the stack by which the object was allocated
michael@0 113 my @stack;
michael@0 114
michael@0 115 while (/^(.*)\[(.*) \+0x(\S+)\]$/) {
michael@0 116 # e.g., _dl_debug_message[/lib/ld-linux.so.2 +0x0000B858]
michael@0 117 my ($func, $lib, $off) = ($1, $2, hex $3);
michael@0 118
michael@0 119 chomp;
michael@0 120 $stack[$#stack + 1] = $_;
michael@0 121
michael@0 122 $_ = <>;
michael@0 123 }
michael@0 124
michael@0 125 $object->{'stack'} = \@stack;
michael@0 126
michael@0 127 $object->{'type'} = infer_type(\@stack)
michael@0 128 if $object->{'type'} eq 'void*';
michael@0 129
michael@0 130 &$callback($object) if $callback;
michael@0 131
michael@0 132 # Gotta check EOF explicitly...
michael@0 133 last OBJECT if eof;
michael@0 134 }
michael@0 135 }
michael@0 136
michael@0 137 1;
michael@0 138 __END__
michael@0 139
michael@0 140 =head1 NAME
michael@0 141
michael@0 142 TraceMalloc - Perl routines to deal with output from ``trace malloc''
michael@0 143 and the Boehm GC
michael@0 144
michael@0 145 =head1 SYNOPSIS
michael@0 146
michael@0 147 use TraceMalloc;
michael@0 148
michael@0 149 TraceMalloc::init_type_inference("types.dat");
michael@0 150 TraceMalloc::read(0);
michael@0 151
michael@0 152 =head1 DESCRIPTION
michael@0 153
michael@0 154 =head1 EXAMPLES
michael@0 155
michael@0 156 =cut

mercurial