| 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 21 matching lines...) Expand all Loading... |
| 32 class Describer(object): | 32 class Describer(object): |
| 33 def __init__(self, verbose=False): | 33 def __init__(self, verbose=False): |
| 34 self.verbose = verbose | 34 self.verbose = verbose |
| 35 | 35 |
| 36 def _DescribeSectionSizes(self, section_sizes): | 36 def _DescribeSectionSizes(self, section_sizes): |
| 37 relevant_names = models.SECTION_TO_SECTION_NAME.values() | 37 relevant_names = models.SECTION_TO_SECTION_NAME.values() |
| 38 section_names = sorted(k for k in section_sizes.iterkeys() | 38 section_names = sorted(k for k in section_sizes.iterkeys() |
| 39 if k in relevant_names or k.startswith('.data')) | 39 if k in relevant_names or k.startswith('.data')) |
| 40 total_bytes = sum(v for k, v in section_sizes.iteritems() | 40 total_bytes = sum(v for k, v in section_sizes.iteritems() |
| 41 if k in section_names and k != '.bss') | 41 if k in section_names and k != '.bss') |
| 42 yield '' |
| 42 yield 'Section Sizes (Total={:,} bytes):'.format(total_bytes) | 43 yield 'Section Sizes (Total={:,} bytes):'.format(total_bytes) |
| 43 for name in section_names: | 44 for name in section_names: |
| 44 size = section_sizes[name] | 45 size = section_sizes[name] |
| 45 if name == '.bss': | 46 if name == '.bss': |
| 46 yield '{}: {:,} bytes (not included in totals)'.format(name, size) | 47 yield ' {}: {:,} bytes (not included in totals)'.format(name, size) |
| 47 else: | 48 else: |
| 48 percent = float(size) / total_bytes if total_bytes else 0 | 49 percent = float(size) / total_bytes if total_bytes else 0 |
| 49 yield '{}: {:,} bytes ({:.1%})'.format(name, size, percent) | 50 yield ' {}: {:,} bytes ({:.1%})'.format(name, size, percent) |
| 50 | 51 |
| 51 if self.verbose: | 52 if self.verbose: |
| 52 yield '' | 53 yield '' |
| 53 yield 'Other section sizes:' | 54 yield 'Other section sizes:' |
| 54 section_names = sorted(k for k in section_sizes.iterkeys() | 55 section_names = sorted(k for k in section_sizes.iterkeys() |
| 55 if k not in section_names) | 56 if k not in section_names) |
| 56 for name in section_names: | 57 for name in section_names: |
| 57 yield '{}: {:,} bytes'.format(name, section_sizes[name]) | 58 yield ' {}: {:,} bytes'.format(name, section_sizes[name]) |
| 58 | 59 |
| 59 def _DescribeSymbol(self, sym): | 60 def _DescribeSymbol(self, sym): |
| 60 # SymbolGroups are passed here when we don't want to expand them. | 61 # SymbolGroups are passed here when we don't want to expand them. |
| 61 if sym.IsGroup(): | 62 if sym.IsGroup(): |
| 62 if self.verbose: | 63 if self.verbose: |
| 63 yield ('{} {:<8} {} (count={}) padding={} ' | 64 yield ('{} {:<8} {} (count={}) padding={} ' |
| 64 'size_without_padding={}').format( | 65 'size_without_padding={}').format( |
| 65 sym.section, sym.size, sym.name, len(sym), sym.padding, | 66 sym.section, sym.size, sym.name, len(sym), sym.padding, |
| 66 sym.size_without_padding) | 67 sym.size_without_padding) |
| 67 else: | 68 else: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 if diff.IsRemoved(sym): | 132 if diff.IsRemoved(sym): |
| 132 return '- ' | 133 return '- ' |
| 133 if sym.size: | 134 if sym.size: |
| 134 return '~ ' | 135 return '~ ' |
| 135 return '= ' | 136 return '= ' |
| 136 | 137 |
| 137 diff = diff if self.verbose else diff.WhereNotUnchanged() | 138 diff = diff if self.verbose else diff.WhereNotUnchanged() |
| 138 group_desc = self._DescribeSymbolGroup(diff, prefix_func=prefix_func) | 139 group_desc = self._DescribeSymbolGroup(diff, prefix_func=prefix_func) |
| 139 return itertools.chain((header_str,), group_desc) | 140 return itertools.chain((header_str,), group_desc) |
| 140 | 141 |
| 142 def _DescribeSizeInfoDiff(self, diff): |
| 143 common_metadata = {k: v for k, v in diff.old_metadata.iteritems() |
| 144 if diff.new_metadata[k] == v} |
| 145 old_metadata = {k: v for k, v in diff.old_metadata.iteritems() |
| 146 if k not in common_metadata} |
| 147 new_metadata = {k: v for k, v in diff.new_metadata.iteritems() |
| 148 if k not in common_metadata} |
| 149 metadata_desc = itertools.chain( |
| 150 ('Common Metadata:',), |
| 151 (' %s' % line for line in DescribeMetadata(common_metadata)), |
| 152 ('Old Metadata:',), |
| 153 (' %s' % line for line in DescribeMetadata(old_metadata)), |
| 154 ('New Metadata:',), |
| 155 (' %s' % line for line in DescribeMetadata(new_metadata))) |
| 156 section_desc = self._DescribeSectionSizes(diff.section_sizes) |
| 157 group_desc = self.GenerateLines(diff.symbols) |
| 158 return itertools.chain(metadata_desc, section_desc, ('',), group_desc) |
| 159 |
| 160 def _DescribeSizeInfo(self, size_info): |
| 161 metadata_desc = itertools.chain( |
| 162 ('Metadata:',), |
| 163 (' %s' % line for line in DescribeMetadata(size_info.metadata))) |
| 164 section_desc = self._DescribeSectionSizes(size_info.section_sizes) |
| 165 group_desc = self.GenerateLines(size_info.symbols) |
| 166 return itertools.chain(metadata_desc, section_desc, ('',), group_desc) |
| 167 |
| 141 def GenerateLines(self, obj): | 168 def GenerateLines(self, obj): |
| 169 if isinstance(obj, models.SizeInfoDiff): |
| 170 return self._DescribeSizeInfoDiff(obj) |
| 142 if isinstance(obj, models.SizeInfo): | 171 if isinstance(obj, models.SizeInfo): |
| 143 metadata_desc = 'Metadata: %s' % DescribeSizeInfoMetadata(obj) | 172 return self._DescribeSizeInfo(obj) |
| 144 section_desc = self._DescribeSectionSizes(obj.section_sizes) | |
| 145 group_desc = self.GenerateLines(obj.symbols) | |
| 146 return itertools.chain((metadata_desc,), section_desc, ('',), group_desc) | |
| 147 | |
| 148 if isinstance(obj, models.SymbolDiff): | 173 if isinstance(obj, models.SymbolDiff): |
| 149 return self._DescribeSymbolDiff(obj) | 174 return self._DescribeSymbolDiff(obj) |
| 150 | |
| 151 if isinstance(obj, models.SymbolGroup): | 175 if isinstance(obj, models.SymbolGroup): |
| 152 return self._DescribeSymbolGroup(obj) | 176 return self._DescribeSymbolGroup(obj) |
| 153 | |
| 154 if isinstance(obj, models.Symbol): | 177 if isinstance(obj, models.Symbol): |
| 155 return self._DescribeSymbol(obj) | 178 return self._DescribeSymbol(obj) |
| 156 | |
| 157 return (repr(obj),) | 179 return (repr(obj),) |
| 158 | 180 |
| 159 | 181 |
| 160 def DescribeSizeInfoCoverage(size_info): | 182 def DescribeSizeInfoCoverage(size_info): |
| 161 """Yields lines describing how accurate |size_info| is.""" | 183 """Yields lines describing how accurate |size_info| is.""" |
| 162 for section in models.SECTION_TO_SECTION_NAME: | 184 for section in models.SECTION_TO_SECTION_NAME: |
| 163 if section == 'd': | 185 if section == 'd': |
| 164 expected_size = sum(v for k, v in size_info.section_sizes.iteritems() | 186 expected_size = sum(v for k, v in size_info.section_sizes.iteritems() |
| 165 if k.startswith('.data')) | 187 if k.startswith('.data')) |
| 166 else: | 188 else: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 192 yield '+ ' + one_stat(attributed_syms) | 214 yield '+ ' + one_stat(attributed_syms) |
| 193 | 215 |
| 194 | 216 |
| 195 def _UtcToLocal(utc): | 217 def _UtcToLocal(utc): |
| 196 epoch = time.mktime(utc.timetuple()) | 218 epoch = time.mktime(utc.timetuple()) |
| 197 offset = (datetime.datetime.fromtimestamp(epoch) - | 219 offset = (datetime.datetime.fromtimestamp(epoch) - |
| 198 datetime.datetime.utcfromtimestamp(epoch)) | 220 datetime.datetime.utcfromtimestamp(epoch)) |
| 199 return utc + offset | 221 return utc + offset |
| 200 | 222 |
| 201 | 223 |
| 202 def DescribeSizeInfoMetadata(size_info): | 224 def DescribeMetadata(metadata): |
| 203 display_dict = size_info.metadata.copy() | 225 display_dict = metadata.copy() |
| 204 timestamp = display_dict.get(models.METADATA_ELF_MTIME) | 226 timestamp = display_dict.get(models.METADATA_ELF_MTIME) |
| 205 if timestamp: | 227 if timestamp: |
| 206 timestamp_obj = datetime.datetime.utcfromtimestamp(timestamp) | 228 timestamp_obj = datetime.datetime.utcfromtimestamp(timestamp) |
| 207 display_dict[models.METADATA_ELF_MTIME] = ( | 229 display_dict[models.METADATA_ELF_MTIME] = ( |
| 208 _UtcToLocal(timestamp_obj).strftime('%Y-%m-%d %H:%M:%S')) | 230 _UtcToLocal(timestamp_obj).strftime('%Y-%m-%d %H:%M:%S')) |
| 209 return ' '.join(sorted('%s=%s' % t for t in display_dict.iteritems())) | 231 gn_args = display_dict.get(models.METADATA_GN_ARGS) |
| 232 if gn_args: |
| 233 display_dict[models.METADATA_GN_ARGS] = '; '.join(gn_args) |
| 234 return sorted('%s=%s' % t for t in display_dict.iteritems()) |
| 210 | 235 |
| 211 | 236 |
| 212 def GenerateLines(obj, verbose=False): | 237 def GenerateLines(obj, verbose=False): |
| 213 return Describer(verbose).GenerateLines(obj) | 238 return Describer(verbose).GenerateLines(obj) |
| 214 | 239 |
| 215 | 240 |
| 216 def WriteLines(lines, func): | 241 def WriteLines(lines, func): |
| 217 for l in lines: | 242 for l in lines: |
| 218 func(l) | 243 func(l) |
| 219 func('\n') | 244 func('\n') |
| OLD | NEW |