Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: tools/binary_size/libsupersize/models.py

Issue 2863753005: Supersize: Store whether source path was generated in flags (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 5
6 The primary classes are Symbol, and SymbolGroup. 6 The primary classes are Symbol, and SymbolGroup.
7 7
8 Description of common properties: 8 Description of common properties:
9 * address: The start address of the symbol. 9 * address: The start address of the symbol.
10 May be 0 (e.g. for .bss or for SymbolGroups). 10 May be 0 (e.g. for .bss or for SymbolGroups).
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 'd': '.data', 48 'd': '.data',
49 'r': '.rodata', 49 'r': '.rodata',
50 't': '.text', 50 't': '.text',
51 } 51 }
52 52
53 FLAG_ANONYMOUS = 1 53 FLAG_ANONYMOUS = 1
54 FLAG_STARTUP = 2 54 FLAG_STARTUP = 2
55 FLAG_UNLIKELY = 4 55 FLAG_UNLIKELY = 4
56 FLAG_REL = 8 56 FLAG_REL = 8
57 FLAG_REL_LOCAL = 16 57 FLAG_REL_LOCAL = 16
58 FLAG_GENERATED_SOURCE = 32
58 59
59 60
60 class SizeInfo(object): 61 class SizeInfo(object):
61 """Represents all size information for a single binary. 62 """Represents all size information for a single binary.
62 63
63 Fields: 64 Fields:
64 section_sizes: A dict of section_name -> size. 65 section_sizes: A dict of section_name -> size.
65 symbols: A SymbolGroup containing all symbols, sorted by address. 66 symbols: A SymbolGroup containing all symbols, sorted by address.
66 metadata: A dict. 67 metadata: A dict.
67 """ 68 """
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 130
130 @property 131 @property
131 def end_address(self): 132 def end_address(self):
132 return self.address + self.size_without_padding 133 return self.address + self.size_without_padding
133 134
134 @property 135 @property
135 def is_anonymous(self): 136 def is_anonymous(self):
136 return bool(self.flags & FLAG_ANONYMOUS) 137 return bool(self.flags & FLAG_ANONYMOUS)
137 138
138 @property 139 @property
140 def generated_source(self):
141 return bool(self.flags & FLAG_GENERATED_SOURCE)
142
143 @generated_source.setter
144 def generated_source(self, value):
145 if value:
146 self.flags |= FLAG_GENERATED_SOURCE
147 else:
148 self.flags &= ~FLAG_GENERATED_SOURCE
149
150 @property
139 def num_aliases(self): 151 def num_aliases(self):
140 return len(self.aliases) if self.aliases else 1 152 return len(self.aliases) if self.aliases else 1
141 153
142 def FlagsString(self): 154 def FlagsString(self):
143 # Most flags are 0. 155 # Most flags are 0.
144 flags = self.flags 156 flags = self.flags
145 if not flags and not self.aliases: 157 if not flags and not self.aliases:
146 return '{}' 158 return '{}'
147 parts = [] 159 parts = []
148 if flags & FLAG_ANONYMOUS: 160 if flags & FLAG_ANONYMOUS:
149 parts.append('anon') 161 parts.append('anon')
150 if flags & FLAG_STARTUP: 162 if flags & FLAG_STARTUP:
151 parts.append('startup') 163 parts.append('startup')
152 if flags & FLAG_UNLIKELY: 164 if flags & FLAG_UNLIKELY:
153 parts.append('unlikely') 165 parts.append('unlikely')
154 if flags & FLAG_REL: 166 if flags & FLAG_REL:
155 parts.append('rel') 167 parts.append('rel')
156 if flags & FLAG_REL_LOCAL: 168 if flags & FLAG_REL_LOCAL:
157 parts.append('rel.loc') 169 parts.append('rel.loc')
170 if flags & FLAG_GENERATED_SOURCE:
171 parts.append('gen')
158 # Not actually a part of flags, but useful to show it here. 172 # Not actually a part of flags, but useful to show it here.
159 if self.aliases: 173 if self.aliases:
160 parts.append('{} aliases'.format(self.num_aliases)) 174 parts.append('{} aliases'.format(self.num_aliases))
161 return '{%s}' % ','.join(parts) 175 return '{%s}' % ','.join(parts)
162 176
163 def IsBss(self): 177 def IsBss(self):
164 return self.section_name == '.bss' 178 return self.section_name == '.bss'
165 179
166 def IsGroup(self): 180 def IsGroup(self):
167 return False 181 return False
168 182
169 def IsGenerated(self): 183 def IsGeneratedByToolchain(self):
170 # TODO(agrieve): Also match generated functions such as: 184 return '.' in self.name or (
171 # startup._GLOBAL__sub_I_page_allocator.cc 185 self.name.endswith(']') and not self.name.endswith('[]'))
172 return self.name.endswith(']') and not self.name.endswith('[]')
173 186
174 187
175 class Symbol(BaseSymbol): 188 class Symbol(BaseSymbol):
176 """Represents a single symbol within a binary. 189 """Represents a single symbol within a binary.
177 190
178 Refer to module docs for field descriptions. 191 Refer to module docs for field descriptions.
179 """ 192 """
180 193
181 __slots__ = ( 194 __slots__ = (
182 'address', 195 'address',
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 section_name=self.section_name) 308 section_name=self.section_name)
296 309
297 def __add__(self, other): 310 def __add__(self, other):
298 self_ids = set(id(s) for s in self) 311 self_ids = set(id(s) for s in self)
299 after_symbols = self._symbols + [s for s in other if id(s) not in self_ids] 312 after_symbols = self._symbols + [s for s in other if id(s) not in self_ids]
300 return self._CreateTransformed( 313 return self._CreateTransformed(
301 after_symbols, section_name=self.section_name, is_sorted=False) 314 after_symbols, section_name=self.section_name, is_sorted=False)
302 315
303 @property 316 @property
304 def address(self): 317 def address(self):
305 first = self._symbols[0].address 318 first = self._symbols[0].address if self else 0
estevenson 2017/05/05 19:14:58 probably obvious but what is the "if self" for?
agrieve 2017/05/06 00:37:29 it checks for the case of a SymbolGroup with no ch
306 return first if all(s.address == first for s in self._symbols) else 0 319 return first if all(s.address == first for s in self._symbols) else 0
307 320
308 @property 321 @property
309 def flags(self): 322 def flags(self):
310 first = self._symbols[0].flags 323 first = self._symbols[0].flags if self else 0
311 return first if all(s.flags == first for s in self._symbols) else 0 324 return first if all(s.flags == first for s in self._symbols) else 0
312 325
313 @property 326 @property
314 def object_path(self): 327 def object_path(self):
315 first = self._symbols[0].object_path 328 first = self._symbols[0].object_path if self else ''
316 return first if all(s.object_path == first for s in self._symbols) else '' 329 return first if all(s.object_path == first for s in self._symbols) else ''
317 330
318 @property 331 @property
319 def source_path(self): 332 def source_path(self):
320 first = self._symbols[0].source_path 333 first = self._symbols[0].source_path if self else ''
321 return first if all(s.source_path == first for s in self._symbols) else '' 334 return first if all(s.source_path == first for s in self._symbols) else ''
322 335
323 def IterUniqueSymbols(self): 336 def IterUniqueSymbols(self):
324 seen_aliases_lists = set() 337 seen_aliases_lists = set()
325 for s in self: 338 for s in self:
326 if not s.aliases: 339 if not s.aliases:
327 yield s 340 yield s
328 elif id(s.aliases) not in seen_aliases_lists: 341 elif id(s.aliases) not in seen_aliases_lists:
329 seen_aliases_lists.add(id(s.aliases)) 342 seen_aliases_lists.add(id(s.aliases))
330 yield s 343 yield s
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 436
424 def WhereInSection(self, section): 437 def WhereInSection(self, section):
425 if len(section) == 1: 438 if len(section) == 1:
426 ret = self.Filter(lambda s: s.section == section) 439 ret = self.Filter(lambda s: s.section == section)
427 ret.section_name = SECTION_TO_SECTION_NAME[section] 440 ret.section_name = SECTION_TO_SECTION_NAME[section]
428 else: 441 else:
429 ret = self.Filter(lambda s: s.section_name == section) 442 ret = self.Filter(lambda s: s.section_name == section)
430 ret.section_name = section 443 ret.section_name = section
431 return ret 444 return ret
432 445
433 def WhereIsGenerated(self): 446 def WhereSourceIsGenerated(self):
434 return self.Filter(lambda s: s.IsGenerated()) 447 return self.Filter(lambda s: s.generated_source)
448
449 def WhereGeneratedByToolchain(self):
450 return self.Filter(lambda s: s.IsGeneratedByToolchain())
435 451
436 def WhereNameMatches(self, pattern): 452 def WhereNameMatches(self, pattern):
437 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern)) 453 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
438 return self.Filter(lambda s: regex.search(s.name)) 454 return self.Filter(lambda s: regex.search(s.name))
439 455
456 def WhereFullNameMatches(self, pattern):
estevenson 2017/05/05 19:14:58 Does it make sense to just add this to WhereNameMa
agrieve 2017/05/06 00:37:29 This is certainly a place where I'm not sure what
457 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
458 return self.Filter(lambda s: regex.search(s.full_name or s.name))
459
440 def WhereObjectPathMatches(self, pattern): 460 def WhereObjectPathMatches(self, pattern):
441 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern)) 461 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
442 return self.Filter(lambda s: regex.search(s.object_path)) 462 return self.Filter(lambda s: regex.search(s.object_path))
443 463
444 def WhereSourcePathMatches(self, pattern): 464 def WhereSourcePathMatches(self, pattern):
445 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern)) 465 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
446 return self.Filter(lambda s: regex.search(s.source_path)) 466 return self.Filter(lambda s: regex.search(s.source_path))
447 467
448 def WherePathMatches(self, pattern): 468 def WherePathMatches(self, pattern):
449 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern)) 469 regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
(...skipping 12 matching lines...) Expand all
462 """Searches for addesses within [start, end). 482 """Searches for addesses within [start, end).
463 483
464 Args may be ints or hex strings. Default value for |end| is |start| + 1. 484 Args may be ints or hex strings. Default value for |end| is |start| + 1.
465 """ 485 """
466 if isinstance(start, basestring): 486 if isinstance(start, basestring):
467 start = int(start, 16) 487 start = int(start, 16)
468 if end is None: 488 if end is None:
469 end = start + 1 489 end = start + 1
470 return self.Filter(lambda s: s.address >= start and s.address < end) 490 return self.Filter(lambda s: s.address >= start and s.address < end)
471 491
492 def WhereHasPath(self):
493 return self.Filter(lambda s: s.source_path or s.object_path)
494
472 def WhereHasAnyAttribution(self): 495 def WhereHasAnyAttribution(self):
473 return self.Filter(lambda s: s.name or s.source_path or s.object_path) 496 return self.Filter(lambda s: s.name or s.source_path or s.object_path)
474 497
475 def Inverted(self): 498 def Inverted(self):
476 """Returns the symbols that were filtered out by the previous filter. 499 """Returns the symbols that were filtered out by the previous filter.
477 500
478 Applies only when the previous call was a filter. 501 Applies only when the previous call was a filter.
479 502
480 Example: 503 Example:
481 # Symbols that do not have "third_party" in their path. 504 # Symbols that do not have "third_party" in their path.
482 symbols.WherePathMatches(r'third_party').Inverted() 505 symbols.WherePathMatches(r'third_party').Inverted()
483 # Symbols within third_party that do not contain the string "foo". 506 # Symbols within third_party that do not contain the string "foo".
484 symbols.WherePathMatches(r'third_party').WhereMatches('foo').Inverted() 507 symbols.WherePathMatches(r'third_party').WhereMatches('foo').Inverted()
485 """ 508 """
486 return self._CreateTransformed( 509 return self._CreateTransformed(
487 self._filtered_symbols, filtered_symbols=self._symbols, is_sorted=False) 510 self._filtered_symbols, filtered_symbols=self._symbols, is_sorted=False)
488 511
489 def GroupBy(self, func, min_count=0): 512 def GroupBy(self, func, min_count=0):
490 """Returns a SymbolGroup of SymbolGroups, indexed by |func|. 513 """Returns a SymbolGroup of SymbolGroups, indexed by |func|.
491 514
515 Symbols within each subgroup maintain their relative ordering.
516
492 Args: 517 Args:
493 func: Grouping function. Passed a symbol and returns a string for the 518 func: Grouping function. Passed a symbol and returns a string for the
494 name of the subgroup to put the symbol in. If None is returned, the 519 name of the subgroup to put the symbol in. If None is returned, the
495 symbol is omitted. 520 symbol is omitted.
496 min_count: Miniumum number of symbols for a group. If fewer than this many 521 min_count: Miniumum number of symbols for a group. If fewer than this many
497 symbols end up in a group, they will not be put within a group. 522 symbols end up in a group, they will not be put within a group.
498 Use a negative value to omit symbols entirely rather than 523 Use a negative value to omit symbols entirely rather than
499 include them outside of a group. 524 include them outside of a group.
500 """ 525 """
501 after_syms = [] 526 after_syms = []
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 722
698 def _ExtractPrefixBeforeSeparator(string, separator, count=1): 723 def _ExtractPrefixBeforeSeparator(string, separator, count=1):
699 idx = -len(separator) 724 idx = -len(separator)
700 prev_idx = None 725 prev_idx = None
701 for _ in xrange(count): 726 for _ in xrange(count):
702 idx = string.find(separator, idx + len(separator)) 727 idx = string.find(separator, idx + len(separator))
703 if idx < 0: 728 if idx < 0:
704 break 729 break
705 prev_idx = idx 730 prev_idx = idx
706 return string[:prev_idx] 731 return string[:prev_idx]
OLDNEW
« no previous file with comments | « tools/binary_size/libsupersize/console.py ('k') | tools/binary_size/libsupersize/testdata/Archive_Elf.golden » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698