| 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 """Classes that comprise the data model for binary size analysis.""" | 4 """Classes that comprise the data model for binary size analysis. |
| 5 |
| 6 The primary classes are Symbol, and SymbolGroup. |
| 7 |
| 8 Description of common properties: |
| 9 * address: The start address of the symbol. |
| 10 May be 0 (e.g. for .bss or for SymbolGroups). |
| 11 * size: The number of bytes this symbol takes up, including padding that comes |
| 12 before |address|. |
| 13 * padding: The number of bytes of padding before |address| due to this symbol. |
| 14 * name: Symbol names with parameter list removed. |
| 15 Never None, but will be '' for anonymous symbols. |
| 16 * full_name: Symbols names with parameter list left in. |
| 17 Never None, but will be '' for anonymous symbols, and for symbols that do |
| 18 not contain a parameter list. |
| 19 * is_anonymous: True when the symbol exists in an anonymous namespace (which |
| 20 are removed from both full_name and name during normalization). |
| 21 * section_name: E.g. ".text", ".rodata", ".data.rel.local" |
| 22 * section: The second character of |section_name|. E.g. "t", "r", "d". |
| 23 """ |
| 5 | 24 |
| 6 import collections | 25 import collections |
| 7 import copy | 26 import copy |
| 8 import os | 27 import os |
| 9 import re | 28 import re |
| 10 | 29 |
| 11 import match_util | 30 import match_util |
| 12 | 31 |
| 13 | 32 |
| 33 METADATA_GIT_REVISION = 'git_revision' |
| 34 METADATA_MAP_FILENAME = 'map_file_name' |
| 35 METADATA_ELF_FILENAME = 'elf_file_name' |
| 36 METADATA_ELF_MTIME = 'elf_mtime' # int timestamp in utc. |
| 37 METADATA_ELF_BUILD_ID = 'elf_build_id' |
| 38 |
| 14 SECTION_TO_SECTION_NAME = { | 39 SECTION_TO_SECTION_NAME = { |
| 15 'b': '.bss', | 40 'b': '.bss', |
| 16 'd': '.data', | 41 'd': '.data', |
| 17 'r': '.rodata', | 42 'r': '.rodata', |
| 18 't': '.text', | 43 't': '.text', |
| 19 } | 44 } |
| 20 | 45 |
| 21 | 46 |
| 22 class SizeInfo(object): | 47 class SizeInfo(object): |
| 23 """Represents all size information for a single binary. | 48 """Represents all size information for a single binary. |
| 24 | 49 |
| 25 Fields: | 50 Fields: |
| 26 section_sizes: A dict of section_name -> size. | 51 section_sizes: A dict of section_name -> size. |
| 27 symbols: A SymbolGroup (or SymbolDiff) with all symbols in it. | 52 symbols: A SymbolGroup (or SymbolDiff) with all symbols in it. |
| 53 metadata: A dict. |
| 28 """ | 54 """ |
| 29 __slots__ = ( | 55 __slots__ = ( |
| 30 'section_sizes', | 56 'section_sizes', |
| 31 'symbols', | 57 'symbols', |
| 32 'tag', | 58 'metadata', |
| 33 'timestamp', | |
| 34 ) | 59 ) |
| 35 | 60 |
| 36 """Root size information.""" | 61 """Root size information.""" |
| 37 def __init__(self, section_sizes, symbols, timestamp=None, tag=''): | 62 def __init__(self, section_sizes, symbols, metadata=None): |
| 38 self.section_sizes = section_sizes # E.g. {'.text': 0} | 63 self.section_sizes = section_sizes # E.g. {'.text': 0} |
| 39 self.symbols = symbols # List of symbols sorted by address per-section. | 64 self.symbols = symbols # List of symbols sorted by address per-section. |
| 40 self.timestamp = timestamp # UTC datetime object. | 65 self.metadata = metadata or {} |
| 41 self.tag = tag # E.g. git revision. | |
| 42 assert not tag or '\n' not in tag # Simplifies file format. | |
| 43 | 66 |
| 44 | 67 |
| 45 class BaseSymbol(object): | 68 class BaseSymbol(object): |
| 46 """Base class for Symbol and SymbolGroup.""" | 69 """Base class for Symbol and SymbolGroup. |
| 70 |
| 71 Refer to module docs for field descriptions. |
| 72 """ |
| 47 __slots__ = () | 73 __slots__ = () |
| 48 | 74 |
| 49 @property | 75 @property |
| 50 def section(self): | 76 def section(self): |
| 51 """Returns the one-letter section. | 77 """Returns the one-letter section. |
| 52 | 78 |
| 53 E.g. If section_name == '.rodata', then section == 'r'. | 79 E.g. If section_name == '.rodata', then section == 'r'. |
| 54 """ | 80 """ |
| 55 return self.section_name[1] | 81 return self.section_name[1] |
| 56 | 82 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 76 def _Key(self): | 102 def _Key(self): |
| 77 """Returns a tuple that can be used to see if two Symbol are the same. | 103 """Returns a tuple that can be used to see if two Symbol are the same. |
| 78 | 104 |
| 79 Keys are not guaranteed to be unique within a SymbolGroup. For example, it | 105 Keys are not guaranteed to be unique within a SymbolGroup. For example, it |
| 80 is common to have multiple "** merge strings" symbols, which will have a | 106 is common to have multiple "** merge strings" symbols, which will have a |
| 81 common key.""" | 107 common key.""" |
| 82 return (self.section_name, self.full_name or self.name) | 108 return (self.section_name, self.full_name or self.name) |
| 83 | 109 |
| 84 | 110 |
| 85 class Symbol(BaseSymbol): | 111 class Symbol(BaseSymbol): |
| 86 """Represents a single symbol within a binary.""" | 112 """Represents a single symbol within a binary. |
| 113 |
| 114 Refer to module docs for field descriptions. |
| 115 """ |
| 87 | 116 |
| 88 __slots__ = ( | 117 __slots__ = ( |
| 89 'address', | 118 'address', |
| 90 'full_name', | 119 'full_name', |
| 91 'is_anonymous', | 120 'is_anonymous', |
| 92 'object_path', | 121 'object_path', |
| 93 'name', | 122 'name', |
| 94 'padding', | 123 'padding', |
| 95 'section_name', | 124 'section_name', |
| 96 'source_path', | 125 'source_path', |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 | 608 |
| 580 def _ExtractPrefixBeforeSeparator(string, separator, count=1): | 609 def _ExtractPrefixBeforeSeparator(string, separator, count=1): |
| 581 idx = -len(separator) | 610 idx = -len(separator) |
| 582 prev_idx = None | 611 prev_idx = None |
| 583 for _ in xrange(count): | 612 for _ in xrange(count): |
| 584 idx = string.find(separator, idx + len(separator)) | 613 idx = string.find(separator, idx + len(separator)) |
| 585 if idx < 0: | 614 if idx < 0: |
| 586 break | 615 break |
| 587 prev_idx = idx | 616 prev_idx = idx |
| 588 return string[:prev_idx] | 617 return string[:prev_idx] |
| OLD | NEW |