Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
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 |