tools/trace-malloc/uncategorized.pl

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
-rwxr-xr-x

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 #!/usr/bin/perl -w
michael@0 2 #
michael@0 3 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6
michael@0 7 # This tool is used to construct the ``type inference'' file. It
michael@0 8 # prints the total number of bytes that are attributed to a type that
michael@0 9 # cannot be inferred, grouped by stack trace; e.g.,
michael@0 10 #
michael@0 11 # (100) PR_Malloc
michael@0 12 # (50) foo
michael@0 13 # (50) foo2::foo2
michael@0 14 # (25) bar
michael@0 15 # (25) baz
michael@0 16 # (50) __builtin_new
michael@0 17 # (50) foo2::foo2
michael@0 18 #
michael@0 19 #
michael@0 20 # Which indicates that 100 bytes were allocated by uninferrable
michael@0 21 # classes via PR_Malloc(). Of that 100 bytes, 50 were allocated from
michael@0 22 # calls by foo(), 25 from calls by bar(), and 25 from calls by baz().
michael@0 23 # 50 bytes were allocated by __builtin_new from foo2's ctor.
michael@0 24 #
michael@0 25 #
michael@0 26 # From this, we might be able to infer the type of the object that was
michael@0 27 # created by examining the PR_Malloc() usage in foo() and the
michael@0 28 # ::operator new() usage in foo2(), and could add new type inference
michael@0 29 # rules; e.g.,
michael@0 30 #
michael@0 31 # <unclassified-string>
michael@0 32 # foo
michael@0 33 # foo2
michael@0 34 #
michael@0 35 # # Attribute ::operator new() usage in foo2's ctor to foo2
michael@0 36 # <foo2>
michael@0 37 # __builtin_new
michael@0 38 # foo2::foo2
michael@0 39
michael@0 40 use 5.004;
michael@0 41 use strict;
michael@0 42 use Getopt::Long;
michael@0 43
michael@0 44 # So we can find TraceMalloc.pm
michael@0 45 use FindBin;
michael@0 46 use lib "$FindBin::Bin";
michael@0 47
michael@0 48 use TraceMalloc;
michael@0 49
michael@0 50 # Collect program options
michael@0 51 $::opt_help = 0;
michael@0 52 $::opt_depth = 10;
michael@0 53 $::opt_types = "${FindBin::Bin}/types.dat";
michael@0 54 GetOptions("help", "depth=n", "types=s");
michael@0 55
michael@0 56 if ($::opt_help) {
michael@0 57 die "usage: uncategorized.pl [options] <dumpfile>
michael@0 58 --help Display this message
michael@0 59 --depth=<n> Display at most <n> stack frames
michael@0 60 --types=<file> Read type heuristics from <file>";
michael@0 61 }
michael@0 62
michael@0 63 # Initialize type inference juju from the type file specified by
michael@0 64 # ``--types''.
michael@0 65 TraceMalloc::init_type_inference($::opt_types);
michael@0 66
michael@0 67 # Read the objects from the dump file. For each object, remember up to
michael@0 68 # ``--depth'' stack frames (from the top). Thread together common
michael@0 69 # stack prefixes, accumulating the number of bytes attributed to the
michael@0 70 # prefix.
michael@0 71
michael@0 72 # This'll hold the inverted stacks
michael@0 73 $::Stacks = { '#bytes#' => 0 };
michael@0 74
michael@0 75 sub collect_stacks($) {
michael@0 76 my ($object) = @_;
michael@0 77 my $stack = $object->{'stack'};
michael@0 78
michael@0 79 return unless ($object->{'type'} eq 'void*') && (TraceMalloc::infer_type($stack) eq 'void*');
michael@0 80
michael@0 81 my $count = 0;
michael@0 82 my $link = \%::Stacks;
michael@0 83 FRAME: foreach my $frame (@$stack) {
michael@0 84 last FRAME unless $count++ < $::opt_depth;
michael@0 85
michael@0 86 $link->{'#bytes#'} += $object->{'size'};
michael@0 87 $link->{$frame} = { '#bytes#' => 0 } unless $link->{$frame};
michael@0 88 $link = $link->{$frame};
michael@0 89 }
michael@0 90 }
michael@0 91
michael@0 92 TraceMalloc::read(\&collect_stacks);
michael@0 93
michael@0 94 # Do a depth-first walk of the inverted stack tree.
michael@0 95
michael@0 96 sub walk($$) {
michael@0 97 my ($links, $indent) = @_;
michael@0 98
michael@0 99 my @keys;
michael@0 100 KEY: foreach my $key (keys %$links) {
michael@0 101 next KEY if $key eq '#bytes#';
michael@0 102 $keys[$#keys + 1] = $key;
michael@0 103 }
michael@0 104
michael@0 105 foreach my $key (sort { $links->{$b}->{'#bytes#'} <=> $links->{$a}->{'#bytes#'} } @keys) {
michael@0 106 for (my $i = 0; $i < $indent; ++$i) {
michael@0 107 print " ";
michael@0 108 }
michael@0 109
michael@0 110 print "($links->{$key}->{'#bytes#'}) $key\n";
michael@0 111
michael@0 112 walk($links->{$key}, $indent + 1);
michael@0 113 }
michael@0 114 }
michael@0 115
michael@0 116 walk(\%::Stacks, 0);
michael@0 117

mercurial