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

Unified Diff: tools/binary_size/libsupersize/archive.py

Issue 2816093002: FREEZE.unindexed (Closed)
Patch Set: Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/binary_size/libsupersize/describe.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/binary_size/libsupersize/archive.py
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index 97f12f402b5f9d71234d8f0ffdf003a0e401214e..d2b715d885824d2978c8c10a6c720094fc1ca276 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -11,7 +11,6 @@ import datetime
import gzip
import logging
import os
-import multiprocessing
import posixpath
import re
import subprocess
@@ -26,6 +25,7 @@ import helpers
import linker_map_parser
import models
import ninja_parser
+import nm
import paths
@@ -173,29 +173,30 @@ def _CalculatePadding(symbols):
continue
if symbol.address <= 0 or prev_symbol.address <= 0:
continue
- # Padding-only symbols happen for ** symbol gaps.
- prev_is_padding_only = prev_symbol.size_without_padding == 0
- if symbol.address == prev_symbol.address and not prev_is_padding_only:
- assert False, 'Found duplicate symbols:\n%r\n%r' % (prev_symbol, symbol)
- # Even with symbols at the same address removed, overlaps can still
- # happen. In this case, padding will be negative (and this is fine).
+
+ if symbol.address == prev_symbol.address:
+ # Padding-only symbols happen for ** symbol gaps.
+ prev_is_padding_only = prev_symbol.size_without_padding == 0
+ if not prev_is_padding_only:
+ # Must be an alias. Clone its padding.
+ assert symbol.num_aliases > 1, (
+ 'Found duplicate symbols:\n%r\n%r' % (prev_symbol, symbol))
+ symbol.padding = prev_symbol.padding
+ symbol.size = prev_symbol.size
+ continue
+
padding = symbol.address - prev_symbol.end_address
- # These thresholds were found by manually auditing arm32 Chrome.
- # E.g.: Set them to 0 and see what warnings get logged.
+ # These thresholds were found by experimenting with arm32 Chrome.
+ # 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 (
symbol.section in 'rd' and padding >= 256 or
symbol.section in 't' and padding >= 64):
- # For nm data, this is caused by data that has no associated symbol.
- # The linker map file lists them with no name, but with a file.
- # Example:
- # .data 0x02d42764 0x120 .../V8SharedWorkerGlobalScope.o
- # Where as most look like:
- # .data.MANGLED_NAME...
- logging.debug('Large padding of %d between:\n A) %r\n B) %r' % (
- padding, prev_symbol, symbol))
- continue
+ # Should not happen.
+ logging.warning('Large padding of %d between:\n A) %r\n B) %r' % (
+ padding, prev_symbol, symbol))
+ #continue
symbol.padding = padding
symbol.size += padding
assert symbol.size >= 0, (
@@ -306,6 +307,46 @@ def _ClusterSymbols(symbols):
return grouped_symbols
+def _AddSymbolAliases(symbols, aliases_by_address):
+ # Step 1: Create list of (index_of_symbol, name_list).
+ replacements = []
+ num_new_symbols = 0
+ for i, s in enumerate(symbols):
+ name_list = aliases_by_address.get(s.address)
+ if not name_list:
+ continue
+
+ if s.name not in name_list:
+ logging.warning('Name missing from aliases: %s %s', s.name, name_list)
+ continue
+
+ replacements.append((i, name_list))
+ num_new_symbols += len(name_list) - 1
+
+ # Step 2: Create new symbols.
+ src_cursor_end = len(symbols)
+ symbols += [None] * num_new_symbols
+ dst_cursor_end = len(symbols)
+ num_copied = 0
+ for src_index, name_list in reversed(replacements):
+ 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]
+ src_cursor_end -= 1
+ assert src_cursor_end == src_index
+ num_aliases = len(name_list)
+ for name in name_list:
+ dst_cursor_end -= 1
+ symbols[dst_cursor_end] = models.Symbol(
+ sym.section_name, sym.size, address=sym.address, name=name,
+ num_aliases=num_aliases)
+
+ assert dst_cursor_end == src_cursor_end
+
+
def LoadAndPostProcessSizeInfo(path):
"""Returns a SizeInfo for the given |path|."""
logging.debug('Loading results from: %s', path)
@@ -325,7 +366,7 @@ def _PostProcessSizeInfo(size_info):
logging.info('Processed %d symbols', len(size_info.raw_symbols))
-def CreateSizeInfo(map_path, lazy_paths=None, no_source_paths=False,
+def CreateSizeInfo(map_path, elf_path, lazy_paths=None, no_source_paths=False,
raw_only=False):
"""Creates a SizeInfo from the given map file."""
if not no_source_paths:
@@ -334,10 +375,20 @@ def CreateSizeInfo(map_path, lazy_paths=None, no_source_paths=False,
# tool_prefix needed for c++filt.
lazy_paths.VerifyToolPrefix()
+ if elf_path:
+ nm_result = helpers.ForkAndCall(nm.CollectAliasesByAddress, elf_path,
+ lazy_paths.tool_prefix)
+
with _OpenMaybeGz(map_path) as map_file:
section_sizes, raw_symbols = (
linker_map_parser.MapFileParser().Parse(map_file))
+ if elf_path:
+ logging.debug('Validating section sizes')
+ elf_section_sizes = _SectionSizesFromElf(elf_path, lazy_paths.tool_prefix)
+ for k, v in elf_section_sizes.iteritems():
+ assert v == section_sizes.get(k), 'ELF file and .map file do not match.'
+
if not no_source_paths:
logging.info('Extracting source paths from .ninja files')
all_found = _ExtractSourcePaths(raw_symbols, lazy_paths.output_directory)
@@ -348,6 +399,13 @@ def CreateSizeInfo(map_path, lazy_paths=None, no_source_paths=False,
# Unmangle prints its own log statement.
_UnmangleRemainingSymbols(raw_symbols, lazy_paths.tool_prefix)
logging.info('Normalizing object paths')
+
+ # See which symbols are shared.
+ if elf_path:
+ logging.info('Adding aliased symbols reported by nm')
+ aliases_by_address = nm_result.get()
+ _AddSymbolAliases(raw_symbols, aliases_by_address)
+
_NormalizeObjectPaths(raw_symbols)
size_info = models.SizeInfo(section_sizes, raw_symbols)
@@ -514,21 +572,15 @@ def Run(args, parser):
if apk_path:
metadata[models.METADATA_APK_FILENAME] = relative_to_out(apk_path)
# Extraction takes around 1 second, so do it in parallel.
- pool_of_one = multiprocessing.Pool(1)
- apk_elf_result = pool_of_one.apply_async(
- _ElfInfoFromApk, (apk_path, apk_so_path, lazy_paths.tool_prefix))
- pool_of_one.close()
+ apk_elf_result = helpers.ForkAndCall(
+ _ElfInfoFromApk, apk_path, apk_so_path, lazy_paths.tool_prefix)
size_info = CreateSizeInfo(
- map_path, lazy_paths, no_source_paths=args.no_source_paths, raw_only=True)
+ map_path, elf_path, lazy_paths, no_source_paths=args.no_source_paths,
+ raw_only=True)
if metadata:
size_info.metadata = metadata
- logging.debug('Validating section sizes')
- elf_section_sizes = _SectionSizesFromElf(elf_path, lazy_paths.tool_prefix)
- for k, v in elf_section_sizes.iteritems():
- assert v == size_info.section_sizes.get(k), (
- 'ELF file and .map file do not match.')
if apk_path:
logging.debug('Extracting section sizes from .so within .apk')
« no previous file with comments | « no previous file | tools/binary_size/libsupersize/describe.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698