| 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 """Methods for converting model objects to human-readable formats.""" | 4 """Methods for converting model objects to human-readable formats.""" |
| 5 | 5 |
| 6 import datetime | 6 import datetime |
| 7 import itertools | 7 import itertools |
| 8 import time | 8 import time |
| 9 | 9 |
| 10 import models | 10 import models |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 def _Divide(a, b): | 48 def _Divide(a, b): |
| 49 return float(a) / b if b else 0 | 49 return float(a) / b if b else 0 |
| 50 | 50 |
| 51 | 51 |
| 52 class Describer(object): | 52 class Describer(object): |
| 53 def __init__(self, verbose=False, recursive=False): | 53 def __init__(self, verbose=False, recursive=False): |
| 54 self.verbose = verbose | 54 self.verbose = verbose |
| 55 self.recursive = recursive | 55 self.recursive = recursive |
| 56 | 56 |
| 57 def _DescribeSectionSizes(self, section_sizes): | 57 def _DescribeSectionSizes(self, section_sizes): |
| 58 relevant_names = models.SECTION_TO_SECTION_NAME.values() | 58 def include_in_totals(name): |
| 59 section_names = sorted(k for k in section_sizes.iterkeys() | 59 return name != '.bss' and '(' not in name |
| 60 if k in relevant_names or k.startswith('.data')) | 60 |
| 61 total_bytes = sum(v for k, v in section_sizes.iteritems() | 61 total_bytes = sum(v for k, v in section_sizes.iteritems() |
| 62 if k in section_names and k != '.bss') | 62 if include_in_totals(k)) |
| 63 max_bytes = max(abs(v) for k, v in section_sizes.iteritems() |
| 64 if include_in_totals(k)) |
| 65 |
| 66 def is_relevant_section(name, size): |
| 67 # Show all sections containing symbols, plus relocations. |
| 68 # As a catch-all, also include any section that comprises > 4% of the |
| 69 # largest section. Use largest section rather than total so that it still |
| 70 # works out when showing a diff containing +100, -100 (total=0). |
| 71 return (name in models.SECTION_TO_SECTION_NAME.values() or |
| 72 name in ('.rela.dyn', '.rel.dyn') or |
| 73 include_in_totals(name) and abs(_Divide(size, max_bytes)) > .04) |
| 74 |
| 75 section_names = sorted(k for k, v in section_sizes.iteritems() |
| 76 if is_relevant_section(k, v)) |
| 63 yield '' | 77 yield '' |
| 64 yield 'Section Sizes (Total={} ({} bytes)):'.format( | 78 yield 'Section Sizes (Total={} ({} bytes)):'.format( |
| 65 _PrettySize(total_bytes), total_bytes) | 79 _PrettySize(total_bytes), total_bytes) |
| 66 for name in section_names: | 80 for name in section_names: |
| 67 size = section_sizes[name] | 81 size = section_sizes[name] |
| 68 if name == '.bss': | 82 if not include_in_totals(name): |
| 69 yield ' {}: {} ({} bytes) (not included in totals)'.format( | 83 yield ' {}: {} ({} bytes) (not included in totals)'.format( |
| 70 name, _PrettySize(size), size) | 84 name, _PrettySize(size), size) |
| 71 else: | 85 else: |
| 72 percent = _Divide(size, total_bytes) | 86 percent = _Divide(size, total_bytes) |
| 73 yield ' {}: {} ({} bytes) ({:.1%})'.format( | 87 yield ' {}: {} ({} bytes) ({:.1%})'.format( |
| 74 name, _PrettySize(size), size, percent) | 88 name, _PrettySize(size), size, percent) |
| 75 | 89 |
| 76 if self.verbose: | 90 if self.verbose: |
| 77 yield '' | 91 yield '' |
| 78 yield 'Other section sizes:' | 92 yield 'Other section sizes:' |
| 79 section_names = sorted(k for k in section_sizes.iterkeys() | 93 section_names = sorted(k for k in section_sizes.iterkeys() |
| 80 if k not in section_names) | 94 if k not in section_names) |
| 81 for name in section_names: | 95 for name in section_names: |
| 82 yield ' {}: {} ({} bytes)'.format( | 96 not_included_part = '' |
| 83 name, _PrettySize(section_sizes[name]), section_sizes[name]) | 97 if not include_in_totals(name): |
| 98 not_included_part = ' (not included in totals)' |
| 99 yield ' {}: {} ({} bytes){}'.format( |
| 100 name, _PrettySize(section_sizes[name]), section_sizes[name], |
| 101 not_included_part) |
| 84 | 102 |
| 85 def _DescribeSymbol(self, sym, single_line=False): | 103 def _DescribeSymbol(self, sym, single_line=False): |
| 86 if sym.IsGroup(): | 104 if sym.IsGroup(): |
| 87 address = 'Group' | 105 address = 'Group' |
| 88 else: | 106 else: |
| 89 address = hex(sym.address) | 107 address = hex(sym.address) |
| 90 if self.verbose: | 108 if self.verbose: |
| 91 count_part = ' count=%d' % len(sym) if sym.IsGroup() else '' | 109 count_part = ' count=%d' % len(sym) if sym.IsGroup() else '' |
| 92 yield '{}@{:<9s} pss={} padding={} size_without_padding={}{}'.format( | 110 yield '{}@{:<9s} pss={} padding={} size_without_padding={}{}'.format( |
| 93 sym.section, address, _FormatPss(sym.pss), sym.padding, | 111 sym.section, address, _FormatPss(sym.pss), sym.padding, |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 | 357 |
| 340 def GenerateLines(obj, verbose=False, recursive=False): | 358 def GenerateLines(obj, verbose=False, recursive=False): |
| 341 """Returns an iterable of lines (without \n) that describes |obj|.""" | 359 """Returns an iterable of lines (without \n) that describes |obj|.""" |
| 342 return Describer(verbose=verbose, recursive=recursive).GenerateLines(obj) | 360 return Describer(verbose=verbose, recursive=recursive).GenerateLines(obj) |
| 343 | 361 |
| 344 | 362 |
| 345 def WriteLines(lines, func): | 363 def WriteLines(lines, func): |
| 346 for l in lines: | 364 for l in lines: |
| 347 func(l) | 365 func(l) |
| 348 func('\n') | 366 func('\n') |
| OLD | NEW |