| Index: tools/binary_size/libsupersize/archive.py
|
| diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
|
| index 0559adc5fc341673373d0fdf9bca01e05ded6078..a32d5738a1c6eea308d669adb2a675f07c46fd6e 100644
|
| --- a/tools/binary_size/libsupersize/archive.py
|
| +++ b/tools/binary_size/libsupersize/archive.py
|
| @@ -44,86 +44,85 @@ def _StripLinkerAddedSymbolPrefixes(raw_symbols):
|
| Removing prefixes make symbol names match up with those found in .o files.
|
| """
|
| for symbol in raw_symbols:
|
| - name = symbol.name
|
| - if name.startswith('startup.'):
|
| + full_name = symbol.full_name
|
| + if full_name.startswith('startup.'):
|
| symbol.flags |= models.FLAG_STARTUP
|
| - symbol.name = name[8:]
|
| - elif name.startswith('unlikely.'):
|
| + symbol.full_name = full_name[8:]
|
| + elif full_name.startswith('unlikely.'):
|
| symbol.flags |= models.FLAG_UNLIKELY
|
| - symbol.name = name[9:]
|
| - elif name.startswith('rel.local.'):
|
| + symbol.full_name = full_name[9:]
|
| + elif full_name.startswith('rel.local.'):
|
| symbol.flags |= models.FLAG_REL_LOCAL
|
| - symbol.name = name[10:]
|
| - elif name.startswith('rel.'):
|
| + symbol.full_name = full_name[10:]
|
| + elif full_name.startswith('rel.'):
|
| symbol.flags |= models.FLAG_REL
|
| - symbol.name = name[4:]
|
| + symbol.full_name = full_name[4:]
|
|
|
|
|
| def _UnmangleRemainingSymbols(raw_symbols, tool_prefix):
|
| """Uses c++filt to unmangle any symbols that need it."""
|
| - to_process = [s for s in raw_symbols if s.name.startswith('_Z')]
|
| + to_process = [s for s in raw_symbols if s.full_name.startswith('_Z')]
|
| if not to_process:
|
| return
|
|
|
| logging.info('Unmangling %d names', len(to_process))
|
| proc = subprocess.Popen([tool_prefix + 'c++filt'], stdin=subprocess.PIPE,
|
| stdout=subprocess.PIPE)
|
| - stdout = proc.communicate('\n'.join(s.name for s in to_process))[0]
|
| + stdout = proc.communicate('\n'.join(s.full_name for s in to_process))[0]
|
| assert proc.returncode == 0
|
|
|
| for i, line in enumerate(stdout.splitlines()):
|
| - to_process[i].name = line
|
| + to_process[i].full_name = line
|
|
|
|
|
| -def _NormalizeNames(symbols):
|
| +def _NormalizeNames(raw_symbols):
|
| """Ensures that all names are formatted in a useful way.
|
|
|
| This includes:
|
| - - Assigning of |full_name|.
|
| - - Stripping of return types in |full_name| and |name| (for functions).
|
| - - Stripping parameters from |name|.
|
| + - Deriving |name| and |template_name| from |full_name|.
|
| + - Stripping of return types (for functions).
|
| - Moving "vtable for" and the like to be suffixes rather than prefixes.
|
| """
|
| found_prefixes = set()
|
| - for symbol in symbols:
|
| - if symbol.name.startswith('*'):
|
| + for symbol in raw_symbols:
|
| + if symbol.full_name.startswith('*'):
|
| # See comment in _CalculatePadding() about when this
|
| # can happen.
|
| + symbol.template_name = symbol.full_name
|
| + symbol.name = symbol.full_name
|
| continue
|
|
|
| # E.g.: vtable for FOO
|
| - idx = symbol.name.find(' for ', 0, 30)
|
| + idx = symbol.full_name.find(' for ', 0, 30)
|
| if idx != -1:
|
| - found_prefixes.add(symbol.name[:idx + 4])
|
| - symbol.name = symbol.name[idx + 5:] + ' [' + symbol.name[:idx] + ']'
|
| + found_prefixes.add(symbol.full_name[:idx + 4])
|
| + symbol.full_name = (
|
| + symbol.full_name[idx + 5:] + ' [' + symbol.full_name[:idx] + ']')
|
|
|
| # E.g.: virtual thunk to FOO
|
| - idx = symbol.name.find(' to ', 0, 30)
|
| + idx = symbol.full_name.find(' to ', 0, 30)
|
| if idx != -1:
|
| - found_prefixes.add(symbol.name[:idx + 3])
|
| - symbol.name = symbol.name[idx + 4:] + ' [' + symbol.name[:idx] + ']'
|
| + found_prefixes.add(symbol.full_name[:idx + 3])
|
| + symbol.full_name = (
|
| + symbol.full_name[idx + 4:] + ' [' + symbol.full_name[:idx] + ']')
|
|
|
| - # Strip out return type, and identify where parameter list starts.
|
| - if symbol.section == 't':
|
| - symbol.full_name, symbol.name = function_signature.Parse(symbol.name)
|
| + # Strip out return type, and split out name, template_name.
|
| + # Function parsing also applies to non-text symbols. E.g. Function statics.
|
| + symbol.full_name, symbol.template_name, symbol.name = (
|
| + function_signature.Parse(symbol.full_name))
|
|
|
| # Remove anonymous namespaces (they just harm clustering).
|
| - non_anonymous = symbol.name.replace('(anonymous namespace)::', '')
|
| - if symbol.name != non_anonymous:
|
| + symbol.template_name = symbol.template_name.replace(
|
| + '(anonymous namespace)::', '')
|
| + symbol.full_name = symbol.full_name.replace(
|
| + '(anonymous namespace)::', '')
|
| + non_anonymous_name = symbol.name.replace('(anonymous namespace)::', '')
|
| + if symbol.name != non_anonymous_name:
|
| symbol.flags |= models.FLAG_ANONYMOUS
|
| - symbol.name = non_anonymous
|
| - symbol.full_name = symbol.full_name.replace(
|
| - '(anonymous namespace)::', '')
|
| -
|
| - if symbol.section != 't' and '(' in symbol.name:
|
| - # Pretty rare. Example:
|
| - # blink::CSSValueKeywordsHash::findValueImpl(char const*)::value_word_list
|
| - symbol.full_name = symbol.name
|
| - symbol.name = re.sub(r'\(.*\)', '', symbol.full_name)
|
| + symbol.name = non_anonymous_name
|
|
|
| - # Don't bother storing both if they are the same.
|
| - if symbol.full_name == symbol.name:
|
| - symbol.full_name = ''
|
| + # Allow using "is" to compare names (and should help with RAM).
|
| + function_signature.InternSameNames(symbol)
|
|
|
| logging.debug('Found name prefixes of: %r', found_prefixes)
|
|
|
| @@ -199,15 +198,15 @@ def _ComputeAnscestorPathsAndNormalizeObjectPaths(
|
| num_path_mismatches = 0
|
| num_unmatched_aliases = 0
|
| for symbol in raw_symbols:
|
| - name = symbol.name
|
| + full_name = symbol.full_name
|
| if (symbol.IsBss() or
|
| - not name or
|
| - name[0] in '*.' or # e.g. ** merge symbols, .Lswitch.table
|
| - name == 'startup'):
|
| + not full_name or
|
| + full_name[0] in '*.' or # e.g. ** merge symbols, .Lswitch.table
|
| + full_name == 'startup'):
|
| symbol.object_path = _NormalizeObjectPath(symbol.object_path)
|
| continue
|
|
|
| - object_paths = object_paths_by_name.get(name)
|
| + object_paths = object_paths_by_name.get(full_name)
|
| if object_paths:
|
| num_found_paths += 1
|
| else:
|
| @@ -263,14 +262,14 @@ def _DiscoverMissedObjectPaths(raw_symbols, elf_object_paths):
|
| return missed_inputs
|
|
|
|
|
| -def _CalculatePadding(symbols):
|
| +def _CalculatePadding(raw_symbols):
|
| """Populates the |padding| field based on symbol addresses.
|
|
|
| Symbols must already be sorted by |address|.
|
| """
|
| seen_sections = []
|
| - for i, symbol in enumerate(symbols[1:]):
|
| - prev_symbol = symbols[i]
|
| + for i, symbol in enumerate(raw_symbols[1:]):
|
| + prev_symbol = raw_symbols[i]
|
| if prev_symbol.section_name != symbol.section_name:
|
| assert symbol.section_name not in seen_sections, (
|
| 'Input symbols must be sorted by section, then address.')
|
| @@ -293,7 +292,7 @@ def _CalculatePadding(symbols):
|
| # E.g.: Set them to 0 and see what warnings get logged, then take max value.
|
| # TODO(agrieve): See if these thresholds make sense for architectures
|
| # other than arm32.
|
| - if not symbol.name.startswith('*') and (
|
| + if not symbol.full_name.startswith('*') and (
|
| symbol.section in 'rd' and padding >= 256 or
|
| symbol.section in 't' and padding >= 64):
|
| # Should not happen.
|
| @@ -317,13 +316,14 @@ def _AddSymbolAliases(raw_symbols, aliases_by_address):
|
| continue
|
| name_list = aliases_by_address.get(s.address)
|
| if name_list:
|
| - if s.name not in name_list:
|
| - logging.warning('Name missing from aliases: %s %s', s.name, name_list)
|
| + if s.full_name not in name_list:
|
| + logging.warning('Name missing from aliases: %s %s', s.full_name,
|
| + name_list)
|
| continue
|
| replacements.append((i, name_list))
|
| num_new_symbols += len(name_list) - 1
|
|
|
| - if float(num_new_symbols) / len(raw_symbols) < .1:
|
| + if float(num_new_symbols) / len(raw_symbols) < .05:
|
| logging.warning('Number of aliases is oddly low (%.0f%%). It should '
|
| 'usually be around 25%%. Ensure --tool-prefix is correct.',
|
| float(num_new_symbols) / len(raw_symbols) * 100)
|
| @@ -345,9 +345,9 @@ def _AddSymbolAliases(raw_symbols, aliases_by_address):
|
|
|
| # Create aliases (does not bother reusing the existing symbol).
|
| aliases = [None] * len(name_list)
|
| - for i, name in enumerate(name_list):
|
| + for i, full_name in enumerate(name_list):
|
| aliases[i] = models.Symbol(
|
| - sym.section_name, sym.size, address=sym.address, name=name,
|
| + sym.section_name, sym.size, address=sym.address, full_name=full_name,
|
| aliases=aliases)
|
|
|
| dst_cursor_end -= len(aliases)
|
| @@ -366,10 +366,10 @@ def LoadAndPostProcessSizeInfo(path):
|
|
|
| def _PostProcessSizeInfo(size_info):
|
| logging.info('Normalizing symbol names')
|
| - _NormalizeNames(size_info.symbols)
|
| + _NormalizeNames(size_info.raw_symbols)
|
| logging.info('Calculating padding')
|
| - _CalculatePadding(size_info.symbols)
|
| - logging.info('Processed %d symbols', len(size_info.symbols))
|
| + _CalculatePadding(size_info.raw_symbols)
|
| + logging.info('Processed %d symbols', len(size_info.raw_symbols))
|
|
|
|
|
| def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory):
|
| @@ -503,22 +503,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, models.SymbolGroup(raw_symbols))
|
| + size_info = models.SizeInfo(section_sizes, raw_symbols)
|
|
|
| # Name normalization not strictly required, but makes for smaller files.
|
| if raw_only:
|
| logging.info('Normalizing symbol names')
|
| - _NormalizeNames(size_info.symbols)
|
| + _NormalizeNames(size_info.raw_symbols)
|
| else:
|
| _PostProcessSizeInfo(size_info)
|
|
|
| if logging.getLogger().isEnabledFor(logging.DEBUG):
|
| # Padding is reported in size coverage logs.
|
| if raw_only:
|
| - _CalculatePadding(size_info.symbols)
|
| + _CalculatePadding(size_info.raw_symbols)
|
| for line in describe.DescribeSizeInfoCoverage(size_info):
|
| logging.info(line)
|
| - logging.info('Recorded info for %d symbols', len(size_info.symbols))
|
| + logging.info('Recorded info for %d symbols', len(size_info.raw_symbols))
|
| return size_info
|
|
|
|
|
|
|