| 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 |
| 11 | 11 |
| 12 | 12 |
| 13 def _PrettySize(size): |
| 14 # Arbitrarily chosen cut-off. |
| 15 if abs(size) < 2000: |
| 16 return '%d bytes' % size |
| 17 # Always show 3 digits. |
| 18 size /= 1024.0 |
| 19 if abs(size) < 10: |
| 20 return '%.2fkb' % size |
| 21 elif abs(size) < 100: |
| 22 return '%.1fkb' % size |
| 23 elif abs(size) < 1024: |
| 24 return '%dkb' % size |
| 25 size /= 1024.0 |
| 26 if abs(size) < 10: |
| 27 return '%.2fmb' % size |
| 28 # We shouldn't be seeing sizes > 100mb. |
| 29 return '%.1fmb' % size |
| 30 |
| 31 |
| 13 class Describer(object): | 32 class Describer(object): |
| 14 def __init__(self, verbose=False): | 33 def __init__(self, verbose=False): |
| 15 self.verbose = verbose | 34 self.verbose = verbose |
| 16 | 35 |
| 17 def _DescribeSectionSizes(self, section_sizes): | 36 def _DescribeSectionSizes(self, section_sizes): |
| 18 relevant_names = models.SECTION_TO_SECTION_NAME.values() | 37 relevant_names = models.SECTION_TO_SECTION_NAME.values() |
| 19 section_names = sorted(k for k in section_sizes.iterkeys() | 38 section_names = sorted(k for k in section_sizes.iterkeys() |
| 20 if k in relevant_names or k.startswith('.data')) | 39 if k in relevant_names or k.startswith('.data')) |
| 21 total_bytes = sum(v for k, v in section_sizes.iteritems() | 40 total_bytes = sum(v for k, v in section_sizes.iteritems() |
| 22 if k in section_names and k != '.bss') | 41 if k in section_names and k != '.bss') |
| 23 yield 'Section Sizes (Total={:,} bytes):'.format(total_bytes) | 42 yield 'Section Sizes (Total={:,} bytes):'.format(total_bytes) |
| 24 for name in section_names: | 43 for name in section_names: |
| 25 size = section_sizes[name] | 44 size = section_sizes[name] |
| 26 if name == '.bss': | 45 if name == '.bss': |
| 27 yield '{}: {:,} bytes (not included in totals)'.format(name, size) | 46 yield '{}: {:,} bytes (not included in totals)'.format(name, size) |
| 28 else: | 47 else: |
| 29 percent = float(size) / total_bytes if total_bytes else 0 | 48 percent = float(size) / total_bytes if total_bytes else 0 |
| 30 yield '{}: {:,} bytes ({:.1%})'.format(name, size, percent) | 49 yield '{}: {:,} bytes ({:.1%})'.format(name, size, percent) |
| 31 | 50 |
| 32 def _DescribeSymbol(self, sym): | 51 def _DescribeSymbol(self, sym): |
| 33 # SymbolGroups are passed here when we don't want to expand them. | 52 # SymbolGroups are passed here when we don't want to expand them. |
| 34 if sym.IsGroup(): | 53 if sym.IsGroup(): |
| 35 yield '{} {:<8} {} (count={})'.format(sym.section, sym.size, sym.name, | 54 if self.verbose: |
| 36 len(sym)) | 55 yield ('{} {:<8} {} (count={}) padding={} ' |
| 56 'size_without_padding={}').format( |
| 57 sym.section, sym.size, sym.name, len(sym), sym.padding, |
| 58 sym.size_without_padding) |
| 59 else: |
| 60 yield '{} {:<8} {} (count={})'.format(sym.section, sym.size, sym.name, |
| 61 len(sym)) |
| 37 return | 62 return |
| 38 | 63 |
| 39 yield '{}@0x{:<8x} {:<7} {}'.format( | 64 if self.verbose: |
| 40 sym.section, sym.address, sym.size, | 65 yield '{}@0x{:<8x} size={} padding={} size_without_padding={}'.format( |
| 41 sym.source_path or sym.object_path or '{no path}') | 66 sym.section, sym.address, sym.size, sym.padding, |
| 42 if sym.name: | 67 sym.size_without_padding) |
| 43 yield '{:22}{}'.format('', sym.name) | 68 yield ' source_path={} \tobject_path={}'.format( |
| 69 sym.source_path, sym.object_path) |
| 70 if sym.full_name: |
| 71 yield ' full_name={} \tis_anonymous={}'.format( |
| 72 sym.full_name, sym.is_anonymous) |
| 73 if sym.name: |
| 74 yield ' name={} \tis_anonymous={}'.format( |
| 75 sym.name, sym.is_anonymous) |
| 76 else: |
| 77 yield '{}@0x{:<8x} {:<7} {}'.format( |
| 78 sym.section, sym.address, sym.size, |
| 79 sym.source_path or sym.object_path or '{no path}') |
| 80 if sym.name: |
| 81 yield ' {}'.format(sym.name) |
| 44 | 82 |
| 45 def _DescribeSymbolGroup(self, group, prefix_func=None): | 83 def _DescribeSymbolGroup(self, group, prefix_func=None): |
| 46 yield 'Showing {:,} symbols with total size: {:} bytes'.format( | 84 total_size = group.size |
| 47 len(group), group.size) | 85 yield 'Showing {:,} symbols with total size: {} bytes'.format( |
| 86 len(group), total_size) |
| 87 code_syms = group.WhereInSection('t') |
| 88 code_size = code_syms.size |
| 89 ro_size = code_syms.Inverted().WhereInSection('r').size |
| 90 yield '.text={:<10} .rodata={:<10} other={:<10} total={}'.format( |
| 91 _PrettySize(code_size), _PrettySize(ro_size), |
| 92 _PrettySize(total_size - code_size - ro_size), |
| 93 _PrettySize(total_size)) |
| 48 yield 'First columns are: running total, type, size' | 94 yield 'First columns are: running total, type, size' |
| 49 | 95 |
| 50 running_total = 0 | 96 running_total = 0 |
| 51 prefix = '' | 97 prefix = '' |
| 98 sorted_syms = group if group.is_sorted else group.Sorted() |
| 52 | 99 |
| 53 for s in group.Sorted(): | 100 prefix = '' |
| 101 for s in sorted_syms: |
| 54 if group.IsBss() or not s.IsBss(): | 102 if group.IsBss() or not s.IsBss(): |
| 55 running_total += s.size | 103 running_total += s.size |
| 56 if prefix_func: | |
| 57 prefix = prefix_func(s) | |
| 58 for l in self._DescribeSymbol(s): | 104 for l in self._DescribeSymbol(s): |
| 59 yield '{}{:8} {}'.format(prefix, running_total, l) | 105 if l[:4].isspace(): |
| 106 yield '{} {}'.format(' ' * (8 + len(prefix)), l) |
| 107 else: |
| 108 if prefix_func: |
| 109 prefix = prefix_func(s) |
| 110 yield '{}{:8} {}'.format(prefix, running_total, l) |
| 60 | 111 |
| 61 def _DescribeSymbolDiff(self, diff): | 112 def _DescribeSymbolDiff(self, diff): |
| 62 template = ('{} symbols added (+), {} changed (~), {} removed (-), ' | 113 template = ('{} symbols added (+), {} changed (~), {} removed (-), ' |
| 63 '{} unchanged ({})') | 114 '{} unchanged ({})') |
| 64 unchanged_msg = '=' if self.verbose else 'not shown' | 115 unchanged_msg = '=' if self.verbose else 'not shown' |
| 65 header_str = (template.format( | 116 header_str = (template.format( |
| 66 diff.added_count, diff.changed_count, diff.removed_count, | 117 diff.added_count, diff.changed_count, diff.removed_count, |
| 67 diff.unchanged_count, unchanged_msg)) | 118 diff.unchanged_count, unchanged_msg)) |
| 68 | 119 |
| 69 def prefix_func(sym): | 120 def prefix_func(sym): |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 epoch = time.mktime(utc.timetuple()) | 188 epoch = time.mktime(utc.timetuple()) |
| 138 offset = (datetime.datetime.fromtimestamp(epoch) - | 189 offset = (datetime.datetime.fromtimestamp(epoch) - |
| 139 datetime.datetime.utcfromtimestamp(epoch)) | 190 datetime.datetime.utcfromtimestamp(epoch)) |
| 140 return utc + offset | 191 return utc + offset |
| 141 | 192 |
| 142 | 193 |
| 143 def DescribeSizeInfoMetadata(size_info): | 194 def DescribeSizeInfoMetadata(size_info): |
| 144 time_str = 'Unknown' | 195 time_str = 'Unknown' |
| 145 if size_info.timestamp: | 196 if size_info.timestamp: |
| 146 time_str = _UtcToLocal(size_info.timestamp).strftime('%Y-%m-%d %H:%M:%S') | 197 time_str = _UtcToLocal(size_info.timestamp).strftime('%Y-%m-%d %H:%M:%S') |
| 147 return 'time=%s tag=%s' % (time_str, size_info.tag) | 198 return 'mapfile mtime=%s \ttag=%s' % (time_str, size_info.tag) |
| 148 | 199 |
| 149 | 200 |
| 150 def GenerateLines(obj, verbose=False): | 201 def GenerateLines(obj, verbose=False): |
| 151 return Describer(verbose).GenerateLines(obj) | 202 return Describer(verbose).GenerateLines(obj) |
| 152 | 203 |
| 153 | 204 |
| 154 def WriteLines(lines, func): | 205 def WriteLines(lines, func): |
| 155 for l in lines: | 206 for l in lines: |
| 156 func(l) | 207 func(l) |
| 157 func('\n') | 208 func('\n') |
| OLD | NEW |