| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 with open(to_file, 'w') as file_obj: | 60 with open(to_file, 'w') as file_obj: |
| 61 describe.WriteLines(lines, file_obj.write) | 61 describe.WriteLines(lines, file_obj.write) |
| 62 else: | 62 else: |
| 63 describe.WriteLines(lines, sys.stdout.write) | 63 describe.WriteLines(lines, sys.stdout.write) |
| 64 | 64 |
| 65 | 65 |
| 66 class _Session(object): | 66 class _Session(object): |
| 67 _readline_initialized = False | 67 _readline_initialized = False |
| 68 | 68 |
| 69 def __init__(self, size_infos, size_paths, lazy_paths): | 69 def __init__(self, size_infos, size_paths, lazy_paths): |
| 70 self._printed_variables = [] |
| 70 self._variables = { | 71 self._variables = { |
| 71 'Print': self._PrintFunc, | 72 'Print': self._PrintFunc, |
| 72 'Diff': self._DiffFunc, | 73 'Diff': self._DiffFunc, |
| 73 'Disassemble': self._DisassembleFunc, | 74 'Disassemble': self._DisassembleFunc, |
| 74 'ExpandRegex': match_util.ExpandRegexIdentifierPlaceholder, | 75 'ExpandRegex': match_util.ExpandRegexIdentifierPlaceholder, |
| 75 'ShowExamples': self._ShowExamplesFunc, | 76 'ShowExamples': self._ShowExamplesFunc, |
| 76 'canned_queries': canned_queries.CannedQueries(size_infos), | 77 'canned_queries': canned_queries.CannedQueries(size_infos), |
| 78 'printed': self._printed_variables, |
| 77 } | 79 } |
| 78 self._lazy_paths = lazy_paths | 80 self._lazy_paths = lazy_paths |
| 79 self._size_infos = size_infos | 81 self._size_infos = size_infos |
| 80 self._size_paths = size_paths | 82 self._size_paths = size_paths |
| 81 self._disassemble_prefix_len = None | 83 self._disassemble_prefix_len = None |
| 82 | 84 |
| 83 if len(size_infos) == 1: | 85 if len(size_infos) == 1: |
| 84 self._variables['size_info'] = size_infos[0] | 86 self._variables['size_info'] = size_infos[0] |
| 85 else: | 87 else: |
| 86 for i, size_info in enumerate(size_infos): | 88 for i, size_info in enumerate(size_infos): |
| (...skipping 15 matching lines...) Expand all Loading... |
| 102 if cluster: | 104 if cluster: |
| 103 ret.symbols = ret.symbols.Clustered() | 105 ret.symbols = ret.symbols.Clustered() |
| 104 if sort: | 106 if sort: |
| 105 ret.symbols = ret.symbols.Sorted() | 107 ret.symbols = ret.symbols.Sorted() |
| 106 return ret | 108 return ret |
| 107 | 109 |
| 108 def _PrintFunc(self, obj=None, verbose=False, recursive=False, use_pager=None, | 110 def _PrintFunc(self, obj=None, verbose=False, recursive=False, use_pager=None, |
| 109 to_file=None): | 111 to_file=None): |
| 110 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo. | 112 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo. |
| 111 | 113 |
| 114 For convenience, |obj| will be appended to the global "printed" list. |
| 115 |
| 112 Args: | 116 Args: |
| 113 obj: The object to be printed. Defaults to size_infos[-1]. | 117 obj: The object to be printed. Defaults to size_infos[-1]. |
| 114 verbose: Show more detailed output. | 118 verbose: Show more detailed output. |
| 115 recursive: Print children of nested SymbolGroups. | 119 recursive: Print children of nested SymbolGroups. |
| 116 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol. | 120 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol. |
| 117 default is to automatically pipe when output is long. | 121 default is to automatically pipe when output is long. |
| 118 to_file: Rather than print to stdio, write to the given file. | 122 to_file: Rather than print to stdio, write to the given file. |
| 119 """ | 123 """ |
| 124 if not self._printed_variables or self._printed_variables[-1] != obj: |
| 125 self._printed_variables.append(obj) |
| 120 obj = obj if obj is not None else self._size_infos[-1] | 126 obj = obj if obj is not None else self._size_infos[-1] |
| 121 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive) | 127 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive) |
| 122 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) | 128 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) |
| 123 | 129 |
| 124 def _ElfPathAndToolPrefixForSymbol(self, symbol, elf_path, tool_prefix): | 130 def _ElfPathAndToolPrefixForSymbol(self, symbol, elf_path, tool_prefix): |
| 125 size_info = None | 131 size_info = None |
| 126 size_path = None | 132 size_path = None |
| 127 for size_info, size_path in zip(self._size_infos, self._size_paths): | 133 for size_info, size_path in zip(self._size_infos, self._size_paths): |
| 128 if symbol in size_info.symbols: | 134 if symbol in size_info.symbols: |
| 129 break | 135 break |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 | 195 |
| 190 def _DisassembleFunc(self, symbol, elf_path=None, use_pager=None, | 196 def _DisassembleFunc(self, symbol, elf_path=None, use_pager=None, |
| 191 to_file=None): | 197 to_file=None): |
| 192 """Shows objdump disassembly for the given symbol. | 198 """Shows objdump disassembly for the given symbol. |
| 193 | 199 |
| 194 Args: | 200 Args: |
| 195 symbol: Must be a .text symbol and not a SymbolGroup. | 201 symbol: Must be a .text symbol and not a SymbolGroup. |
| 196 elf_path: Path to the executable containing the symbol. Required only | 202 elf_path: Path to the executable containing the symbol. Required only |
| 197 when auto-detection fails. | 203 when auto-detection fails. |
| 198 """ | 204 """ |
| 205 assert not symbol.IsGroup() |
| 199 assert symbol.address and symbol.section_name == '.text' | 206 assert symbol.address and symbol.section_name == '.text' |
| 200 | 207 |
| 201 tool_prefix = self._lazy_paths.tool_prefix | 208 tool_prefix = self._lazy_paths.tool_prefix |
| 202 if not elf_path: | 209 if not elf_path: |
| 203 elf_path, tool_prefix = self._ElfPathAndToolPrefixForSymbol( | 210 elf_path, tool_prefix = self._ElfPathAndToolPrefixForSymbol( |
| 204 symbol, elf_path, tool_prefix) | 211 symbol, elf_path, tool_prefix) |
| 205 | 212 |
| 206 args = [tool_prefix + 'objdump', '--disassemble', '--source', | 213 args = [tool_prefix + 'objdump', '--disassemble', '--source', |
| 207 '--line-numbers', '--demangle', | 214 '--line-numbers', '--demangle', |
| 208 '--start-address=0x%x' % symbol.address, | 215 '--start-address=0x%x' % symbol.address, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 'help(models)', | 247 'help(models)', |
| 241 '', | 248 '', |
| 242 '# Show all attributes of all symbols & per-section totals:', | 249 '# Show all attributes of all symbols & per-section totals:', |
| 243 'Print(size_info, verbose=True)', | 250 'Print(size_info, verbose=True)', |
| 244 '', | 251 '', |
| 245 '# Show two levels of .text, grouped by first two subdirectories', | 252 '# Show two levels of .text, grouped by first two subdirectories', |
| 246 'text_syms = size_info.symbols.WhereInSection("t")', | 253 'text_syms = size_info.symbols.WhereInSection("t")', |
| 247 'by_path = text_syms.GroupedByPath(depth=2)', | 254 'by_path = text_syms.GroupedByPath(depth=2)', |
| 248 'Print(by_path.WherePssBiggerThan(1024))', | 255 'Print(by_path.WherePssBiggerThan(1024))', |
| 249 '', | 256 '', |
| 250 '# Show all non-vtable generated symbols', | 257 '# Show all generated symbols, then show only non-vtable ones', |
| 251 'generated_syms = size_info.symbols.WhereGeneratedByToolchain()', | 258 'Print(size_info.symbols.WhereGeneratedByToolchain())', |
| 252 'Print(generated_syms.WhereNameMatches(r"vtable").Inverted().Sorted())', | 259 'Print(printed[-1].WhereNameMatches(r"vtable").Inverted().Sorted())', |
| 253 '', | 260 '', |
| 254 '# Show all symbols that have "print" in their name or path, except', | 261 '# Show all symbols that have "print" in their name or path, except', |
| 255 '# those within components/.', | 262 '# those within components/.', |
| 256 '# Note: Could have also used Inverted(), as above.', | 263 '# Note: Could have also used Inverted(), as above.', |
| 257 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.', | 264 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.', |
| 258 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")', | 265 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")', |
| 259 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))', | 266 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))', |
| 260 '', | 267 '', |
| 261 '# Diff two .size files and save result to a file:', | 268 '# Diff two .size files and save result to a file:', |
| 262 'Print(Diff(size_info1, size_info2), to_file="output.txt")', | 269 'Print(Diff(size_info1, size_info2), to_file="output.txt")', |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 output_directory=args.output_directory, | 355 output_directory=args.output_directory, |
| 349 any_path_within_output_directory=args.inputs[0]) | 356 any_path_within_output_directory=args.inputs[0]) |
| 350 session = _Session(size_infos, args.inputs, lazy_paths) | 357 session = _Session(size_infos, args.inputs, lazy_paths) |
| 351 | 358 |
| 352 if args.query: | 359 if args.query: |
| 353 logging.info('Running query from command-line.') | 360 logging.info('Running query from command-line.') |
| 354 session.Eval(args.query) | 361 session.Eval(args.query) |
| 355 else: | 362 else: |
| 356 logging.info('Entering interactive console.') | 363 logging.info('Entering interactive console.') |
| 357 session.GoInteractive() | 364 session.GoInteractive() |
| OLD | NEW |