| Index: tools/binary_size/libsupersize/archive.py
|
| diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
|
| index 68b1cf5fbfe447067f51aa70aebdda54c05f0893..72a0a95d19ba5ff9704e0e44af41952c9677fc02 100644
|
| --- a/tools/binary_size/libsupersize/archive.py
|
| +++ b/tools/binary_size/libsupersize/archive.py
|
| @@ -38,12 +38,12 @@ def _OpenMaybeGz(path, mode=None):
|
| return open(path, mode or 'r')
|
|
|
|
|
| -def _StripLinkerAddedSymbolPrefixes(symbols):
|
| +def _StripLinkerAddedSymbolPrefixes(raw_symbols):
|
| """Removes prefixes sometimes added to symbol names during link
|
|
|
| Removing prefixes make symbol names match up with those found in .o files.
|
| """
|
| - for symbol in symbols:
|
| + for symbol in raw_symbols:
|
| name = symbol.name
|
| if name.startswith('startup.'):
|
| symbol.flags |= models.FLAG_STARTUP
|
| @@ -59,9 +59,9 @@ def _StripLinkerAddedSymbolPrefixes(symbols):
|
| symbol.name = name[4:]
|
|
|
|
|
| -def _UnmangleRemainingSymbols(symbols, tool_prefix):
|
| +def _UnmangleRemainingSymbols(raw_symbols, tool_prefix):
|
| """Uses c++filt to unmangle any symbols that need it."""
|
| - to_process = [s for s in symbols if s.name.startswith('_Z')]
|
| + to_process = [s for s in raw_symbols if s.name.startswith('_Z')]
|
| if not to_process:
|
| return
|
|
|
| @@ -161,10 +161,10 @@ def _SourcePathForObjectPath(object_path, source_mapper):
|
| return ''
|
|
|
|
|
| -def _ExtractSourcePaths(symbols, source_mapper):
|
| +def _ExtractSourcePaths(raw_symbols, source_mapper):
|
| """Fills in the |source_path| attribute."""
|
| logging.debug('Parsed %d .ninja files.', source_mapper.parsed_file_count)
|
| - for symbol in symbols:
|
| + for symbol in raw_symbols:
|
| object_path = symbol.object_path
|
| if object_path and not symbol.source_path:
|
| symbol.source_path = _SourcePathForObjectPath(object_path, source_mapper)
|
| @@ -190,12 +190,12 @@ def _ComputeAnscestorPath(path_list):
|
| # This must normalize object paths at the same time because normalization
|
| # needs to occur before finding common ancestor.
|
| def _ComputeAnscestorPathsAndNormalizeObjectPaths(
|
| - symbols, object_paths_by_name, source_mapper):
|
| + raw_symbols, object_paths_by_name, source_mapper):
|
| num_found_paths = 0
|
| num_unknown_names = 0
|
| num_path_mismatches = 0
|
| num_unmatched_aliases = 0
|
| - for symbol in symbols:
|
| + for symbol in raw_symbols:
|
| name = symbol.name
|
| if (symbol.IsBss() or
|
| not name or
|
| @@ -244,12 +244,12 @@ def _ComputeAnscestorPathsAndNormalizeObjectPaths(
|
| num_path_mismatches, num_unmatched_aliases)
|
|
|
|
|
| -def _DiscoverMissedObjectPaths(symbols, elf_object_paths):
|
| +def _DiscoverMissedObjectPaths(raw_symbols, elf_object_paths):
|
| # Missing object paths are caused by .a files added by -l flags, which are not
|
| # listed as explicit inputs within .ninja rules.
|
| parsed_inputs = set(elf_object_paths)
|
| missed_inputs = set()
|
| - for symbol in symbols:
|
| + for symbol in raw_symbols:
|
| path = symbol.object_path
|
| if path.endswith(')'):
|
| # Convert foo/bar.a(baz.o) -> foo/bar.a
|
| @@ -302,115 +302,12 @@ def _CalculatePadding(symbols):
|
| '%r\nprev symbol: %r' % (symbol, prev_symbol))
|
|
|
|
|
| -def _ClusterSymbols(symbols):
|
| - """Returns a new list of symbols with some symbols moved into groups.
|
| -
|
| - Groups include:
|
| - * Symbols that have [clone] in their name (created by compiler optimization).
|
| - * Star symbols (such as "** merge strings", and "** symbol gap")
|
| -
|
| - To view created groups:
|
| - Print(size_info.symbols.Filter(lambda s: s.IsGroup()), recursive=True)
|
| - """
|
| - # http://unix.stackexchange.com/questions/223013/function-symbol-gets-part-suffix-after-compilation
|
| - # Example name suffixes:
|
| - # [clone .part.322] # GCC
|
| - # [clone .isra.322] # GCC
|
| - # [clone .constprop.1064] # GCC
|
| - # [clone .11064] # clang
|
| -
|
| - # Step 1: Create name map, find clones, collect star syms into replacements.
|
| - logging.debug('Creating name -> symbol map')
|
| - clone_indices = []
|
| - indices_by_full_name = {}
|
| - # (name, full_name) -> [(index, sym),...]
|
| - replacements_by_name = collections.defaultdict(list)
|
| - for i, symbol in enumerate(symbols):
|
| - if symbol.name.startswith('**'):
|
| - # "symbol gap 3" -> "symbol gaps"
|
| - name = re.sub(r'\s+\d+$', 's', symbol.name)
|
| - replacements_by_name[(name, None)].append((i, symbol))
|
| - elif symbol.full_name:
|
| - if symbol.full_name.endswith(']') and ' [clone ' in symbol.full_name:
|
| - clone_indices.append(i)
|
| - else:
|
| - indices_by_full_name[symbol.full_name] = i
|
| -
|
| - # Step 2: Collect same-named clone symbols.
|
| - logging.debug('Grouping all clones')
|
| - group_names_by_index = {}
|
| - for i in clone_indices:
|
| - symbol = symbols[i]
|
| - # Multiple attributes could exist, so search from left-to-right.
|
| - stripped_name = symbol.name[:symbol.name.index(' [clone ')]
|
| - stripped_full_name = symbol.full_name[:symbol.full_name.index(' [clone ')]
|
| - name_tup = (stripped_name, stripped_full_name)
|
| - replacement_list = replacements_by_name[name_tup]
|
| -
|
| - if not replacement_list:
|
| - # First occurance, check for non-clone symbol.
|
| - non_clone_idx = indices_by_full_name.get(stripped_name)
|
| - if non_clone_idx is not None:
|
| - non_clone_symbol = symbols[non_clone_idx]
|
| - replacement_list.append((non_clone_idx, non_clone_symbol))
|
| - group_names_by_index[non_clone_idx] = stripped_name
|
| -
|
| - replacement_list.append((i, symbol))
|
| - group_names_by_index[i] = stripped_name
|
| -
|
| - # Step 3: Undo clustering when length=1.
|
| - # Removing these groups means Diff() logic must know about [clone] suffix.
|
| - to_clear = []
|
| - for name_tup, replacement_list in replacements_by_name.iteritems():
|
| - if len(replacement_list) == 1:
|
| - to_clear.append(name_tup)
|
| - for name_tup in to_clear:
|
| - del replacements_by_name[name_tup]
|
| -
|
| - # Step 4: Replace first symbol from each cluster with a SymbolGroup.
|
| - before_symbol_count = sum(len(x) for x in replacements_by_name.itervalues())
|
| - logging.debug('Creating %d symbol groups from %d symbols. %d clones had only '
|
| - 'one symbol.', len(replacements_by_name), before_symbol_count,
|
| - len(to_clear))
|
| -
|
| - len_delta = len(replacements_by_name) - before_symbol_count
|
| - grouped_symbols = [None] * (len(symbols) + len_delta)
|
| - dest_index = 0
|
| - src_index = 0
|
| - seen_names = set()
|
| - replacement_names_by_index = {}
|
| - for name_tup, replacement_list in replacements_by_name.iteritems():
|
| - for tup in replacement_list:
|
| - replacement_names_by_index[tup[0]] = name_tup
|
| -
|
| - sorted_items = replacement_names_by_index.items()
|
| - sorted_items.sort(key=lambda tup: tup[0])
|
| - for index, name_tup in sorted_items:
|
| - count = index - src_index
|
| - grouped_symbols[dest_index:dest_index + count] = (
|
| - symbols[src_index:src_index + count])
|
| - src_index = index + 1
|
| - dest_index += count
|
| - if name_tup not in seen_names:
|
| - seen_names.add(name_tup)
|
| - group_symbols = [tup[1] for tup in replacements_by_name[name_tup]]
|
| - grouped_symbols[dest_index] = models.SymbolGroup(
|
| - group_symbols, name=name_tup[0], full_name=name_tup[1],
|
| - section_name=group_symbols[0].section_name)
|
| - dest_index += 1
|
| -
|
| - assert len(grouped_symbols[dest_index:None]) == len(symbols[src_index:None])
|
| - grouped_symbols[dest_index:None] = symbols[src_index:None]
|
| - logging.debug('Finished making groups.')
|
| - return grouped_symbols
|
| -
|
| -
|
| -def _AddSymbolAliases(symbols, aliases_by_address):
|
| +def _AddSymbolAliases(raw_symbols, aliases_by_address):
|
| # Step 1: Create list of (index_of_symbol, name_list).
|
| logging.debug('Creating alias list')
|
| replacements = []
|
| num_new_symbols = 0
|
| - for i, s in enumerate(symbols):
|
| + for i, s in enumerate(raw_symbols):
|
| # Don't alias padding-only symbols (e.g. ** symbol gap)
|
| if s.size_without_padding == 0:
|
| continue
|
| @@ -424,17 +321,17 @@ def _AddSymbolAliases(symbols, aliases_by_address):
|
|
|
| # Step 2: Create new symbols as siblings to each existing one.
|
| logging.debug('Creating %d aliases', num_new_symbols)
|
| - src_cursor_end = len(symbols)
|
| - symbols += [None] * num_new_symbols
|
| - dst_cursor_end = len(symbols)
|
| + src_cursor_end = len(raw_symbols)
|
| + raw_symbols += [None] * num_new_symbols
|
| + dst_cursor_end = len(raw_symbols)
|
| for src_index, name_list in reversed(replacements):
|
| # Copy over symbols that come after the current one.
|
| chunk_size = src_cursor_end - src_index - 1
|
| dst_cursor_end -= chunk_size
|
| src_cursor_end -= chunk_size
|
| - symbols[dst_cursor_end:dst_cursor_end + chunk_size] = (
|
| - symbols[src_cursor_end:src_cursor_end + chunk_size])
|
| - sym = symbols[src_index]
|
| + raw_symbols[dst_cursor_end:dst_cursor_end + chunk_size] = (
|
| + raw_symbols[src_cursor_end:src_cursor_end + chunk_size])
|
| + sym = raw_symbols[src_index]
|
| src_cursor_end -= 1
|
|
|
| # Create aliases (does not bother reusing the existing symbol).
|
| @@ -445,7 +342,7 @@ def _AddSymbolAliases(symbols, aliases_by_address):
|
| aliases=aliases)
|
|
|
| dst_cursor_end -= len(aliases)
|
| - symbols[dst_cursor_end:dst_cursor_end + len(aliases)] = aliases
|
| + raw_symbols[dst_cursor_end:dst_cursor_end + len(aliases)] = aliases
|
|
|
| assert dst_cursor_end == src_cursor_end
|
|
|
| @@ -460,13 +357,10 @@ def LoadAndPostProcessSizeInfo(path):
|
|
|
| def _PostProcessSizeInfo(size_info):
|
| logging.info('Normalizing symbol names')
|
| - _NormalizeNames(size_info.raw_symbols)
|
| + _NormalizeNames(size_info.symbols)
|
| logging.info('Calculating padding')
|
| - _CalculatePadding(size_info.raw_symbols)
|
| - logging.info('Grouping decomposed functions')
|
| - size_info.symbols = models.SymbolGroup(
|
| - _ClusterSymbols(size_info.raw_symbols))
|
| - logging.info('Processed %d symbols', len(size_info.raw_symbols))
|
| + _CalculatePadding(size_info.symbols)
|
| + logging.info('Processed %d symbols', len(size_info.symbols))
|
|
|
|
|
| def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory):
|
| @@ -599,22 +493,22 @@ def CreateSizeInfo(map_path, elf_path, tool_prefix, output_directory,
|
| for symbol in raw_symbols:
|
| symbol.object_path = _NormalizeObjectPath(symbol.object_path)
|
|
|
| - size_info = models.SizeInfo(section_sizes, raw_symbols)
|
| + size_info = models.SizeInfo(section_sizes, models.SymbolGroup(raw_symbols))
|
|
|
| # Name normalization not strictly required, but makes for smaller files.
|
| if raw_only:
|
| logging.info('Normalizing symbol names')
|
| - _NormalizeNames(size_info.raw_symbols)
|
| + _NormalizeNames(size_info.symbols)
|
| else:
|
| _PostProcessSizeInfo(size_info)
|
|
|
| if logging.getLogger().isEnabledFor(logging.DEBUG):
|
| # Padding is reported in size coverage logs.
|
| if raw_only:
|
| - _CalculatePadding(size_info.raw_symbols)
|
| + _CalculatePadding(size_info.symbols)
|
| for line in describe.DescribeSizeInfoCoverage(size_info):
|
| logging.info(line)
|
| - logging.info('Recorded info for %d symbols', len(size_info.raw_symbols))
|
| + logging.info('Recorded info for %d symbols', len(size_info.symbols))
|
| return size_info
|
|
|
|
|
|
|