| OLD | NEW |
| (Empty) | |
| 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 |
| 3 # found in the LICENSE file. |
| 4 """Methods for converting model objects to human-readable formats.""" |
| 5 |
| 6 import itertools |
| 7 |
| 8 import models |
| 9 |
| 10 |
| 11 class Describer(object): |
| 12 def __init__(self, verbose=False): |
| 13 self.verbose = verbose |
| 14 |
| 15 def _DescribeSectionSizes(self, section_sizes): |
| 16 relevant_names = models.SECTION_TO_SECTION_NAME.values() |
| 17 section_names = sorted(k for k in section_sizes.iterkeys() |
| 18 if k in relevant_names or k.startswith('.data')) |
| 19 total_bytes = sum(v for k, v in section_sizes.iteritems() |
| 20 if k in section_names and k != '.bss') |
| 21 yield 'Section Sizes (Total={:,} bytes):'.format(total_bytes) |
| 22 for name in section_names: |
| 23 size = section_sizes[name] |
| 24 if name == '.bss': |
| 25 yield '{}: {:,} bytes (not included in totals)'.format(name, size) |
| 26 else: |
| 27 percent = float(size) / total_bytes if total_bytes else 0 |
| 28 yield '{}: {:,} bytes ({:.1%})'.format(name, size, percent) |
| 29 |
| 30 def _DescribeSymbol(self, sym): |
| 31 # SymbolGroups are passed here when we don't want to expand them. |
| 32 if sym.IsGroup(): |
| 33 yield '{} {:<8} {} (count={})'.format(sym.section, sym.size, sym.name, |
| 34 len(sym)) |
| 35 return |
| 36 |
| 37 yield '{}@0x{:<8x} {:<7} {}'.format( |
| 38 sym.section, sym.address, sym.virtual_size, sym.path or '<no path>') |
| 39 if sym.name: |
| 40 yield '{:22}{}'.format('', sym.name) |
| 41 |
| 42 def _DescribeSymbolGroup(self, group, prefix_func=None): |
| 43 yield 'Showing {:,} symbols with total size: {:} bytes'.format( |
| 44 len(group), group.size) |
| 45 yield 'First columns are: running total, type, size' |
| 46 |
| 47 running_total = 0 |
| 48 prefix = '' |
| 49 |
| 50 for s in group.Sorted(): |
| 51 running_total += s.size |
| 52 if prefix_func: |
| 53 prefix = prefix_func(s) |
| 54 for l in self._DescribeSymbol(s): |
| 55 yield '{}{:8} {}'.format(prefix, running_total, l) |
| 56 |
| 57 def _DescribeSymbolDiff(self, diff): |
| 58 template = ('{} symbols added (+), {} changed (~), {} removed (-), ' |
| 59 '{} unchanged ({})') |
| 60 unchanged_msg = '=' if self.verbose else 'not shown' |
| 61 header_str = (template.format( |
| 62 diff.added_count, diff.changed_count, diff.removed_count, |
| 63 diff.unchanged_count, unchanged_msg)) |
| 64 |
| 65 def prefix_func(sym): |
| 66 if diff.IsAdded(sym): |
| 67 return '+ ' |
| 68 if diff.IsRemoved(sym): |
| 69 return '- ' |
| 70 if sym.size: |
| 71 return '~ ' |
| 72 return '= ' |
| 73 |
| 74 diff = diff if self.verbose else diff.WhereNotUnchanged() |
| 75 group_desc = self._DescribeSymbolGroup(diff, prefix_func=prefix_func) |
| 76 return itertools.chain((header_str,), group_desc) |
| 77 |
| 78 def GenerateLines(self, obj): |
| 79 if isinstance(obj, models.SizeInfo): |
| 80 section_desc = self._DescribeSectionSizes(obj.section_sizes) |
| 81 group_desc = self.GenerateLines(obj.symbols) |
| 82 return itertools.chain(section_desc, ('',), group_desc) |
| 83 |
| 84 if isinstance(obj, models.SymbolDiff): |
| 85 return self._DescribeSymbolDiff(obj) |
| 86 |
| 87 if isinstance(obj, models.SymbolGroup): |
| 88 return self._DescribeSymbolGroup(obj) |
| 89 |
| 90 if isinstance(obj, models.Symbol): |
| 91 return self._DescribeSymbol(obj) |
| 92 |
| 93 return (repr(obj),) |
| 94 |
| 95 |
| 96 def GenerateLines(obj, verbose=False): |
| 97 return Describer(verbose).GenerateLines(obj) |
| 98 |
| 99 |
| 100 def WriteLines(lines, func): |
| 101 for l in lines: |
| 102 func(l) |
| 103 func('\n') |
| OLD | NEW |