| OLD | NEW |
| 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 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 self._size_infos = size_infos | 81 self._size_infos = size_infos |
| 82 self._size_paths = size_paths | 82 self._size_paths = size_paths |
| 83 self._disassemble_prefix_len = None | 83 self._disassemble_prefix_len = None |
| 84 | 84 |
| 85 if len(size_infos) == 1: | 85 if len(size_infos) == 1: |
| 86 self._variables['size_info'] = size_infos[0] | 86 self._variables['size_info'] = size_infos[0] |
| 87 else: | 87 else: |
| 88 for i, size_info in enumerate(size_infos): | 88 for i, size_info in enumerate(size_infos): |
| 89 self._variables['size_info%d' % (i + 1)] = size_info | 89 self._variables['size_info%d' % (i + 1)] = size_info |
| 90 | 90 |
| 91 def _DiffFunc(self, before=None, after=None, cluster=True, sort=True): | 91 def _DiffFunc(self, before=None, after=None, sort=True): |
| 92 """Diffs two SizeInfo objects. Returns a SizeInfoDiff. | 92 """Diffs two SizeInfo objects. Returns a SizeInfoDiff. |
| 93 | 93 |
| 94 Args: | 94 Args: |
| 95 before: Defaults to first size_infos[0]. | 95 before: Defaults to first size_infos[0]. |
| 96 after: Defaults to second size_infos[1]. | 96 after: Defaults to second size_infos[1]. |
| 97 cluster: When True (default), calls SymbolGroup.Clustered() after diffing. | |
| 98 Generally reduces noise. | |
| 99 sort: When True (default), calls SymbolGroup.Sorted() after diffing. | 97 sort: When True (default), calls SymbolGroup.Sorted() after diffing. |
| 100 """ | 98 """ |
| 101 before = before if before is not None else self._size_infos[0] | 99 before = before if before is not None else self._size_infos[0] |
| 102 after = after if after is not None else self._size_infos[1] | 100 after = after if after is not None else self._size_infos[1] |
| 103 ret = diff.Diff(before, after) | 101 ret = diff.Diff(before, after) |
| 104 if cluster: | |
| 105 ret.symbols = ret.symbols.Clustered() | |
| 106 if sort: | 102 if sort: |
| 107 ret.symbols = ret.symbols.Sorted() | 103 ret.symbols = ret.symbols.Sorted() |
| 108 return ret | 104 return ret |
| 109 | 105 |
| 110 def _PrintFunc(self, obj=None, verbose=False, recursive=False, use_pager=None, | 106 def _PrintFunc(self, obj=None, verbose=False, recursive=False, use_pager=None, |
| 111 to_file=None): | 107 to_file=None): |
| 112 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo. | 108 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo. |
| 113 | 109 |
| 114 For convenience, |obj| will be appended to the global "printed" list. | 110 For convenience, |obj| will be appended to the global "printed" list. |
| 115 | 111 |
| 116 Args: | 112 Args: |
| 117 obj: The object to be printed. Defaults to size_infos[-1]. | 113 obj: The object to be printed. Defaults to size_infos[-1]. |
| 118 verbose: Show more detailed output. | 114 verbose: Show more detailed output. |
| 119 recursive: Print children of nested SymbolGroups. | 115 recursive: Print children of nested SymbolGroups. |
| 120 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol. | 116 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol. |
| 121 default is to automatically pipe when output is long. | 117 default is to automatically pipe when output is long. |
| 122 to_file: Rather than print to stdio, write to the given file. | 118 to_file: Rather than print to stdio, write to the given file. |
| 123 """ | 119 """ |
| 124 if not self._printed_variables or self._printed_variables[-1] != obj: | 120 if not self._printed_variables or self._printed_variables[-1] != obj: |
| 125 self._printed_variables.append(obj) | 121 self._printed_variables.append(obj) |
| 126 obj = obj if obj is not None else self._size_infos[-1] | 122 obj = obj if obj is not None else self._size_infos[-1] |
| 127 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive) | 123 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive) |
| 128 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) | 124 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) |
| 129 | 125 |
| 130 def _ElfPathAndToolPrefixForSymbol(self, symbol, elf_path, tool_prefix): | 126 def _ElfPathAndToolPrefixForSymbol(self, symbol, elf_path, tool_prefix): |
| 131 size_info = None | 127 size_info = None |
| 132 size_path = None | 128 size_path = None |
| 133 for size_info, size_path in zip(self._size_infos, self._size_paths): | 129 for size_info, size_path in zip(self._size_infos, self._size_paths): |
| 134 if symbol in size_info.symbols: | 130 if symbol in size_info.raw_symbols: |
| 135 break | 131 break |
| 136 else: | 132 else: |
| 137 # If symbols is from a diff(), use its address+name to find it. | 133 # If symbols is from a diff(), use its address+name to find it. |
| 138 for size_info, size_path in zip(self._size_infos, self._size_paths): | 134 for size_info, size_path in zip(self._size_infos, self._size_paths): |
| 139 matched = size_info.symbols.WhereAddressInRange(symbol.address) | 135 matched = size_info.raw_symbols.WhereAddressInRange(symbol.address) |
| 140 # Use last matched symbol to skip over padding-only symbols. | 136 # Use last matched symbol to skip over padding-only symbols. |
| 141 if len(matched) > 0 and matched[-1].full_name == symbol.full_name: | 137 if len(matched) > 0 and matched[-1].full_name == symbol.full_name: |
| 142 symbol = matched[-1] | 138 symbol = matched[-1] |
| 143 break | 139 break |
| 144 else: | 140 else: |
| 145 assert False, 'Symbol does not belong to a size_info.' | 141 assert False, 'Symbol does not belong to a size_info.' |
| 146 | 142 |
| 147 orig_tool_prefix = size_info.metadata.get(models.METADATA_TOOL_PREFIX) | 143 orig_tool_prefix = size_info.metadata.get(models.METADATA_TOOL_PREFIX) |
| 148 if orig_tool_prefix: | 144 if orig_tool_prefix: |
| 149 orig_tool_prefix = paths.FromSrcRootRelative(orig_tool_prefix) | 145 orig_tool_prefix = paths.FromSrcRootRelative(orig_tool_prefix) |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.', | 260 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.', |
| 265 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")', | 261 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")', |
| 266 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))', | 262 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))', |
| 267 '', | 263 '', |
| 268 '# Diff two .size files and save result to a file:', | 264 '# Diff two .size files and save result to a file:', |
| 269 'Print(Diff(size_info1, size_info2), to_file="output.txt")', | 265 'Print(Diff(size_info1, size_info2), to_file="output.txt")', |
| 270 '', | 266 '', |
| 271 '# View per-component breakdowns, then drill into the last entry.', | 267 '# View per-component breakdowns, then drill into the last entry.', |
| 272 'c = canned_queries.CategorizeByChromeComponent()', | 268 'c = canned_queries.CategorizeByChromeComponent()', |
| 273 'Print(c)', | 269 'Print(c)', |
| 274 'Print(c[-1].GroupedByPath(depth=2).Clustered().Sorted())', | 270 'Print(c[-1].GroupedByPath(depth=2).Sorted())', |
| 275 '', | 271 '', |
| 276 '# For even more inspiration, look at canned_queries.py', | 272 '# For even more inspiration, look at canned_queries.py', |
| 277 '# (and feel free to add your own!).', | 273 '# (and feel free to add your own!).', |
| 278 ]) | 274 ]) |
| 279 | 275 |
| 280 def _CreateBanner(self): | 276 def _CreateBanner(self): |
| 281 symbol_info_keys = sorted(m for m in dir(models.SizeInfo) if m[0] != '_') | 277 symbol_info_keys = sorted(m for m in dir(models.SizeInfo) if m[0] != '_') |
| 282 symbol_keys = sorted(m for m in dir(models.Symbol) if m[0] != '_') | 278 symbol_keys = sorted(m for m in dir(models.Symbol) if m[0] != '_') |
| 283 symbol_group_keys = [m for m in dir(models.SymbolGroup) if m[0] != '_'] | 279 symbol_group_keys = [m for m in dir(models.SymbolGroup) if m[0] != '_'] |
| 284 symbol_diff_keys = sorted(m for m in dir(models.SymbolDiff) | 280 symbol_diff_keys = sorted(m for m in dir(models.SymbolDiff) |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 output_directory=args.output_directory, | 351 output_directory=args.output_directory, |
| 356 any_path_within_output_directory=args.inputs[0]) | 352 any_path_within_output_directory=args.inputs[0]) |
| 357 session = _Session(size_infos, args.inputs, lazy_paths) | 353 session = _Session(size_infos, args.inputs, lazy_paths) |
| 358 | 354 |
| 359 if args.query: | 355 if args.query: |
| 360 logging.info('Running query from command-line.') | 356 logging.info('Running query from command-line.') |
| 361 session.Eval(args.query) | 357 session.Eval(args.query) |
| 362 else: | 358 else: |
| 363 logging.info('Entering interactive console.') | 359 logging.info('Entering interactive console.') |
| 364 session.GoInteractive() | 360 session.GoInteractive() |
| OLD | NEW |