1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
8 from lib
.policy
import PolicySet
9 from lib
.subcommand
import SubCommand
12 LOGGER
= logging
.getLogger('dmprof')
15 class ExpandCommand(SubCommand
):
17 super(ExpandCommand
, self
).__init
__(
18 'Usage: %prog expand <dump> <policy> <component> <depth>')
19 self
._parser
.add_option('--alternative-dirs', dest
='alternative_dirs',
20 metavar
='/path/on/target@/path/on/host[:...]',
21 help='Read files in /path/on/host/ instead of '
22 'files in /path/on/target/.')
24 def do(self
, sys_argv
):
25 options
, args
= self
._parse
_args
(sys_argv
, 4)
27 target_policy
= args
[2]
28 component_name
= args
[3]
30 alternative_dirs_dict
= {}
32 policy_set
= PolicySet
.load(SubCommand
._parse
_policy
_list
(target_policy
))
33 if not policy_set
[target_policy
].find_rule(component_name
):
34 sys
.stderr
.write("ERROR: Component %s not found in policy %s\n"
35 % (component_name
, target_policy
))
38 if options
.alternative_dirs
:
39 for alternative_dir_pair
in options
.alternative_dirs
.split(':'):
40 target_path
, host_path
= alternative_dir_pair
.split('@', 1)
41 alternative_dirs_dict
[target_path
] = host_path
42 (bucket_set
, dump
) = SubCommand
.load_basic_files(
43 dump_path
, False, alternative_dirs
=alternative_dirs_dict
)
45 ExpandCommand
._output
(dump
, policy_set
[target_policy
], bucket_set
,
46 component_name
, int(depth
), sys
.stdout
)
50 def _output(dump
, policy
, bucket_set
, component_name
, depth
, out
):
51 """Prints all stacktraces in a given component of given depth.
55 policy: A Policy object.
56 bucket_set: A BucketSet object.
57 component_name: A name of component for filtering.
58 depth: An integer representing depth to be printed.
59 out: An IO object to output.
63 ExpandCommand
._accumulate
(
64 dump
, policy
, bucket_set
, component_name
, depth
, sizes
)
66 sorted_sizes_list
= sorted(
67 sizes
.iteritems(), key
=(lambda x
: x
[1]), reverse
=True)
69 # TODO(dmikurube): Better formatting.
70 for size_pair
in sorted_sizes_list
:
71 out
.write('%10d %s\n' % (size_pair
[1], size_pair
[0]))
73 LOGGER
.info('total: %d\n' % total
)
76 def _add_size(precedence
, bucket
, depth
, committed
, sizes
):
77 stacktrace_sequence
= precedence
78 for function
, sourcefile
in zip(
79 bucket
.symbolized_stackfunction
[
80 0 : min(len(bucket
.symbolized_stackfunction
), 1 + depth
)],
81 bucket
.symbolized_stacksourcefile
[
82 0 : min(len(bucket
.symbolized_stacksourcefile
), 1 + depth
)]):
83 stacktrace_sequence
+= '%s(@%s) ' % (function
, sourcefile
)
84 if not stacktrace_sequence
in sizes
:
85 sizes
[stacktrace_sequence
] = 0
86 sizes
[stacktrace_sequence
] += committed
89 def _accumulate(dump
, policy
, bucket_set
, component_name
, depth
, sizes
):
93 rule
= policy
.find_rule(component_name
, rule
)
96 if rule
.allocator_type
not in allocator_type
:
97 allocator_type
.append(rule
.allocator_type
)
101 if rule
.allocator_type
== 'malloc':
102 for bucket_id
, _
, committed
, allocs
, frees
in dump
.iter_stacktrace
:
103 bucket
= bucket_set
.get(bucket_id
)
104 if not bucket
or bucket
.allocator_type
== 'malloc':
105 component_match
= policy
.find_malloc(bucket
)
106 elif bucket
.allocator_type
== 'mmap':
110 if component_match
== component_name
:
112 precedence
+= '(alloc=%d) ' % allocs
113 precedence
+= '(free=%d) ' % frees
115 precedence
+= '(type=%s) ' % bucket
.symbolized_typeinfo
116 precedence
+= '(type.name=%s) ' % bucket
.typeinfo_name
117 ExpandCommand
._add
_size
(precedence
, bucket
, depth
, committed
, sizes
)
118 elif rule
.allocator_type
== 'mmap':
119 for _
, region
in dump
.iter_map
:
120 if region
[0] != 'hooked':
122 component_match
, bucket
= policy
.find_mmap(region
, bucket_set
)
123 if component_match
== component_name
:
124 ExpandCommand
._add
_size
('', bucket
, depth
,
125 region
[1]['committed'], sizes
)
126 elif rule
.allocator_type
== 'unhooked':
127 for addr
, region
in dump
.iter_map
:
128 if region
[0] != 'unhooked':
130 component_match
= policy
.find_unhooked(region
)
131 if component_match
== component_name
:
133 precedence
+= '%s-' % hex(addr
[0])[2:]
134 precedence
+= '%s' % hex(addr
[1])[2:]
135 precedence
+= ' %s' % region
[1]['vma']['readable']
136 precedence
+= '%s' % region
[1]['vma']['writable']
137 precedence
+= '%s' % region
[1]['vma']['executable']
138 precedence
+= '%s' % region
[1]['vma']['private']
139 precedence
+= ' %s' % region
[1]['vma']['offset']
140 precedence
+= ' %s:' % region
[1]['vma']['major']
141 precedence
+= '%s' % region
[1]['vma']['minor']
142 precedence
+= ' %s' % region
[1]['vma']['inode']
143 precedence
+= ' %s' % region
[1]['vma']['name']
144 if not precedence
in sizes
:
145 sizes
[precedence
] = 0
146 sizes
[precedence
] += region
[1]['committed']