Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: tools/binary_size/libsupersize/console.py

Issue 2859383003: FREEZE.unindexed (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/binary_size/libsupersize/archive.py ('k') | tools/binary_size/libsupersize/describe.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2017 The Chromium Authors. All rights reserved. 1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """An interactive console for looking analyzing .size files.""" 5 """An interactive console for looking analyzing .size files."""
6 6
7 import argparse 7 import argparse
8 import atexit 8 import atexit
9 import code 9 import code
10 import contextlib 10 import contextlib
11 import itertools 11 import itertools
12 import logging 12 import logging
13 import os 13 import os
14 import readline 14 import readline
15 import subprocess 15 import subprocess
16 import sys 16 import sys
17 17
18 import archive 18 import archive
19 import describe 19 import describe
20 import diff 20 import diff
21 import file_format 21 import file_format
22 import match_util 22 import match_util
23 import models 23 import models
24 import paths 24 import paths
25 import precanned_queries
25 26
26 27
27 # Number of lines before using less for Print(). 28 # Number of lines before using less for Print().
28 _THRESHOLD_FOR_PAGER = 30 29 _THRESHOLD_FOR_PAGER = 30
29 30
30 31
31 @contextlib.contextmanager 32 @contextlib.contextmanager
32 def _LessPipe(): 33 def _LessPipe():
33 """Output to `less`. Yields a file object to write to.""" 34 """Output to `less`. Yields a file object to write to."""
34 try: 35 try:
(...skipping 26 matching lines...) Expand all
61 else: 62 else:
62 describe.WriteLines(lines, sys.stdout.write) 63 describe.WriteLines(lines, sys.stdout.write)
63 64
64 65
65 class _Session(object): 66 class _Session(object):
66 _readline_initialized = False 67 _readline_initialized = False
67 68
68 def __init__(self, size_infos, lazy_paths): 69 def __init__(self, size_infos, lazy_paths):
69 self._variables = { 70 self._variables = {
70 'Print': self._PrintFunc, 71 'Print': self._PrintFunc,
71 'Diff': diff.Diff, 72 'Diff': self._DiffFunc,
73 'CategorizeByChromeComponent': self._CategorizeByChromeComponentFunc,
74 'CategorizeGenerated': self._CategorizeGeneratedFunc,
72 'Disassemble': self._DisassembleFunc, 75 'Disassemble': self._DisassembleFunc,
73 'ExpandRegex': match_util.ExpandRegexIdentifierPlaceholder, 76 'ExpandRegex': match_util.ExpandRegexIdentifierPlaceholder,
74 'ShowExamples': self._ShowExamplesFunc, 77 'ShowExamples': self._ShowExamplesFunc,
75 } 78 }
76 self._lazy_paths = lazy_paths 79 self._lazy_paths = lazy_paths
77 self._size_infos = size_infos 80 self._size_infos = size_infos
78 81
79 if len(size_infos) == 1: 82 if len(size_infos) == 1:
80 self._variables['size_info'] = size_infos[0] 83 self._variables['size_info'] = size_infos[0]
81 else: 84 else:
82 for i, size_info in enumerate(size_infos): 85 for i, size_info in enumerate(size_infos):
83 self._variables['size_info%d' % (i + 1)] = size_info 86 self._variables['size_info%d' % (i + 1)] = size_info
84 87
85 def _PrintFunc(self, obj, verbose=False, recursive=False, use_pager=None, 88 def _DiffFunc(before=None, after=None, cluster=True):
89 """Diffs two SizeInfo objects. Returns a SizeInfoDiff.
90
91 Args:
92 before: Defaults to first size_infos[0].
93 after: Defaults to second size_infos[1].
94 cluster: When True, calls SymbolGroup.Cluster() after diffing. This
95 generally reduces noise.
96 """
97 before = before if before is not None else self._size_infos[0]
98 after = after if after is not None else self._size_infos[1]
99 return diff.Diff(before, after, cluster=cluster)
100
101 def _PrintFunc(self, obj=None, verbose=False, recursive=False, use_pager=None,
86 to_file=None): 102 to_file=None):
87 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo. 103 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo.
88 104
89 Args: 105 Args:
90 obj: The object to be printed. 106 obj: The object to be printed. Defaults to size_infos[-1].
91 verbose: Show more detailed output. 107 verbose: Show more detailed output.
92 recursive: Print children of nested SymbolGroups. 108 recursive: Print children of nested SymbolGroups.
93 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol. 109 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol.
94 default is to automatically pipe when output is long. 110 default is to automatically pipe when output is long.
95 to_file: Rather than print to stdio, write to the given file. 111 to_file: Rather than print to stdio, write to the given file.
96 """ 112 """
113 obj = obj if obj is not None else self._size_infos[-1]
97 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive) 114 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive)
98 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) 115 _WriteToStream(lines, use_pager=use_pager, to_file=to_file)
99 116
117 def _CategorizeByChromeComponentFunc(self, arg=None):
118 """Groups symbols by component using predefined queries.
119
120 Args:
121 arg: A SizeInfo or SymbolGroup. Defaults to the size_infos[-1].
122 """
123 arg = arg if arg is not None else self._size_infos[-1]
124 if isinstance(arg, models.SizeInfo):
125 arg = arg.symbols
126 return precanned_queries.CategorizeByChromeComponent(arg)
127
128 def _CategorizeGeneratedFunc(self, arg=None):
129 """Categorizes symbols from generated sources.
130
131 Args:
132 arg: A SizeInfo or SymbolGroup. Defaults to the size_infos[-1].
133 """
134 arg = arg if arg is not None else self._size_infos[-1]
135 if isinstance(arg, models.SizeInfo):
136 arg = arg.symbols
137 return precanned_queries.CategorizeGenerated(arg)
138
139
100 def _ElfPathForSymbol(self, symbol): 140 def _ElfPathForSymbol(self, symbol):
101 size_info = None 141 size_info = None
102 for size_info in self._size_infos: 142 for size_info in self._size_infos:
103 if symbol in size_info.symbols: 143 if symbol in size_info.symbols:
104 break 144 break
105 else: 145 else:
106 assert False, 'Symbol does not belong to a size_info.' 146 assert False, 'Symbol does not belong to a size_info.'
107 147
108 filename = size_info.metadata.get(models.METADATA_ELF_FILENAME) 148 filename = size_info.metadata.get(models.METADATA_ELF_FILENAME)
109 output_dir = self._lazy_paths.output_directory or '' 149 output_dir = self._lazy_paths.output_directory or ''
(...skipping 23 matching lines...) Expand all
133 '--start-address=0x%x' % symbol.address, 173 '--start-address=0x%x' % symbol.address,
134 '--stop-address=0x%x' % symbol.end_address, elf_path] 174 '--stop-address=0x%x' % symbol.end_address, elf_path]
135 proc = subprocess.Popen(args, stdout=subprocess.PIPE) 175 proc = subprocess.Popen(args, stdout=subprocess.PIPE)
136 lines = itertools.chain(('Showing disassembly for %r' % symbol, 176 lines = itertools.chain(('Showing disassembly for %r' % symbol,
137 'Command: %s' % ' '.join(args)), 177 'Command: %s' % ' '.join(args)),
138 (l.rstrip() for l in proc.stdout)) 178 (l.rstrip() for l in proc.stdout))
139 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) 179 _WriteToStream(lines, use_pager=use_pager, to_file=to_file)
140 proc.kill() 180 proc.kill()
141 181
142 def _ShowExamplesFunc(self): 182 def _ShowExamplesFunc(self):
183 print self._CreateBanner()
143 print '\n'.join([ 184 print '\n'.join([
144 '# Show pydoc for main types:', 185 '# Show pydoc for main types:',
145 'import models', 186 'import models',
146 'help(models)', 187 'help(models)',
147 '', 188 '',
148 '# Show all attributes of all symbols & per-section totals:', 189 '# Show all attributes of all symbols & per-section totals:',
149 'Print(size_info, verbose=True)', 190 'Print(size_info, verbose=True)',
150 '', 191 '',
151 '# Show two levels of .text, grouped by first two subdirectories', 192 '# Show two levels of .text, grouped by first two subdirectories',
152 'text_syms = size_info.symbols.WhereInSection("t")', 193 'text_syms = size_info.symbols.WhereInSection("t")',
153 'by_path = text_syms.GroupBySourcePath(depth=2)', 194 'by_path = text_syms.GroupByPath(depth=2)',
154 'Print(by_path.WhereBiggerThan(1024))', 195 'Print(by_path.WhereBiggerThan(1024))',
155 '', 196 '',
156 '# Show all non-vtable generated symbols', 197 '# Show all non-vtable generated symbols',
157 'generated_syms = size_info.symbols.WhereIsGenerated()', 198 'generated_syms = size_info.symbols.WhereGeneratedByToolchain()',
158 'Print(generated_syms.WhereNameMatches(r"vtable").Inverted())', 199 'Print(generated_syms.WhereNameMatches(r"vtable").Inverted().Sorted())',
159 '', 200 '',
160 '# Show all symbols that have "print" in their name or path, except', 201 '# Show all symbols that have "print" in their name or path, except',
161 '# those within components/.', 202 '# those within components/.',
162 '# Note: Could have also used Inverted(), as above.', 203 '# Note: Could have also used Inverted(), as above.',
163 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.', 204 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.',
164 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")', 205 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")',
165 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))', 206 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))',
166 '', 207 '',
167 '# Diff two .size files and save result to a file:', 208 '# Diff two .size files and save result to a file:',
168 'Print(Diff(size_info1, size_info2), to_file="output.txt")', 209 'Print(Diff(size_info1, size_info2), to_file="output.txt")',
169 '', 210 '',
211 '# View per-component breakdowns, then inspect the "other" subgroup.',
212 'c = GroupByChromeComponent()',
213 'Print(c)',
214 'Print(c[-1].GroupByPath(depth=2))',
170 ]) 215 ])
171 216
172 def _CreateBanner(self): 217 def _CreateBanner(self):
173 symbol_info_keys = sorted(m for m in dir(models.SizeInfo) if m[0] != '_') 218 symbol_info_keys = sorted(m for m in dir(models.SizeInfo) if m[0] != '_')
174 symbol_keys = sorted(m for m in dir(models.Symbol) if m[0] != '_') 219 symbol_keys = sorted(m for m in dir(models.Symbol) if m[0] != '_')
175 symbol_group_keys = [m for m in dir(models.SymbolGroup) if m[0] != '_'] 220 symbol_group_keys = [m for m in dir(models.SymbolGroup) if m[0] != '_']
176 symbol_diff_keys = sorted(m for m in dir(models.SymbolDiff) 221 symbol_diff_keys = sorted(m for m in dir(models.SymbolDiff)
177 if m[0] != '_' and m not in symbol_group_keys) 222 if m[0] != '_' and m not in symbol_group_keys)
178 symbol_group_keys = sorted(m for m in symbol_group_keys 223 symbol_group_keys = sorted(m for m in symbol_group_keys
179 if m not in symbol_keys) 224 if m not in symbol_keys)
180 functions = sorted(k for k in self._variables if k[0].isupper()) 225 functions = sorted(k for k in self._variables if k[0].isupper())
181 variables = sorted(k for k in self._variables if k[0].islower()) 226 variables = sorted(k for k in self._variables if k[0].islower())
182 return '\n'.join([ 227 return '\n'.join([
183 '*' * 80, 228 '*' * 80,
184 'Entering interactive Python shell. Quick reference:', 229 'Entering interactive Python shell. Quick reference:',
185 '', 230 '',
186 'SizeInfo: %s' % ', '.join(symbol_info_keys), 231 'SizeInfo: %s' % ', '.join(symbol_info_keys),
187 'Symbol: %s' % ', '.join(symbol_keys), 232 'Symbol: %s' % ', '.join(symbol_keys),
233 '',
188 'SymbolGroup (extends Symbol): %s' % ', '.join(symbol_group_keys), 234 'SymbolGroup (extends Symbol): %s' % ', '.join(symbol_group_keys),
235 '',
189 'SymbolDiff (extends SymbolGroup): %s' % ', '.join(symbol_diff_keys), 236 'SymbolDiff (extends SymbolGroup): %s' % ', '.join(symbol_diff_keys),
190 '', 237 '',
191 'Functions: %s' % ', '.join('%s()' % f for f in functions), 238 'Functions: %s' % ', '.join('%s()' % f for f in functions),
192 'Variables: %s' % ', '.join(variables), 239 'Variables: %s' % ', '.join(variables),
193 '*' * 80, 240 '*' * 80,
194 ]) 241 ])
195 242
196 @classmethod 243 @classmethod
197 def _InitReadline(cls): 244 def _InitReadline(cls):
198 if cls._readline_initialized: 245 if cls._readline_initialized:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 output_directory=args.output_directory, 288 output_directory=args.output_directory,
242 any_path_within_output_directory=args.inputs[0]) 289 any_path_within_output_directory=args.inputs[0])
243 session = _Session(size_infos, lazy_paths) 290 session = _Session(size_infos, lazy_paths)
244 291
245 if args.query: 292 if args.query:
246 logging.info('Running query from command-line.') 293 logging.info('Running query from command-line.')
247 session.Eval(args.query) 294 session.Eval(args.query)
248 else: 295 else:
249 logging.info('Entering interactive console.') 296 logging.info('Entering interactive console.')
250 session.GoInteractive() 297 session.GoInteractive()
OLDNEW
« no previous file with comments | « tools/binary_size/libsupersize/archive.py ('k') | tools/binary_size/libsupersize/describe.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698