Index: tools/binary_size/run_binary_size_analysis.py |
diff --git a/tools/binary_size/run_binary_size_analysis.py b/tools/binary_size/run_binary_size_analysis.py |
index f2c95b104fe042b38901da1732d22c39de4565a4..23869e0f64cbdfe659eebd310633d990e0cc96c9 100755 |
--- a/tools/binary_size/run_binary_size_analysis.py |
+++ b/tools/binary_size/run_binary_size_analysis.py |
@@ -18,6 +18,7 @@ import optparse |
import os |
import re |
import shutil |
+import struct |
import subprocess |
import sys |
import tempfile |
@@ -654,6 +655,72 @@ def GetNmSymbols(nm_infile, outfile, library, jobs, verbose, |
return list(binary_size_utils.ParseNm(infile)) |
+PAK_RESOURCE_ID_TO_STRING = { "inited": False } |
+ |
+def LoadPakIdsFromResourceFile(filename): |
+ """Given a file name, it loads everything that looks like a resource id |
+ into PAK_RESOURCE_ID_TO_STRING.""" |
+ with open(filename) as resource_header: |
+ for line in resource_header: |
+ if line.startswith("#define "): |
+ line_data = line.split() |
+ if len(line_data) == 3: |
+ try: |
+ resource_number = int(line_data[2]) |
+ resource_name = line_data[1] |
+ PAK_RESOURCE_ID_TO_STRING[resource_number] = resource_name |
+ except ValueError: |
+ pass |
+ |
+def GetReadablePakResourceName(pak_file, resource_id): |
+ """Pak resources have a numeric identifier. It is not helpful when |
+ trying to locate where footprint is generated. This does its best to |
+ map the number to a usable string.""" |
+ if not PAK_RESOURCE_ID_TO_STRING['inited']: |
+ # Try to find resource header files generated by grit when |
+ # building the pak file. We'll look for files named *resources.h" |
+ # and lines of the type: |
+ # #define MY_RESOURCE_JS 1234 |
+ PAK_RESOURCE_ID_TO_STRING['inited'] = True |
+ gen_dir = os.path.join(os.path.dirname(pak_file), 'gen') |
+ if os.path.isdir(gen_dir): |
+ for dirname, _dirs, files in os.walk(gen_dir): |
+ for filename in files: |
+ if filename.endswith('resources.h'): |
+ LoadPakIdsFromResourceFile(os.path.join(dirname, filename)) |
+ return PAK_RESOURCE_ID_TO_STRING.get(resource_id, |
+ 'Pak Resource %d' % resource_id) |
+ |
+def AddPakData(symbols, pak_file): |
+ """Adds pseudo-symbols from a pak file.""" |
+ pak_file = os.path.abspath(pak_file) |
+ with open(pak_file, 'rb') as pak: |
+ data = pak.read() |
+ |
+ PAK_FILE_VERSION = 4 |
+ HEADER_LENGTH = 2 * 4 + 1 # Two uint32s. (file version, number of entries) |
+ # and one uint8 (encoding of text resources) |
+ INDEX_ENTRY_SIZE = 2 + 4 # Each entry is a uint16 and a uint32. |
+ version, num_entries, _encoding = struct.unpack('<IIB', data[:HEADER_LENGTH]) |
+ assert version == PAK_FILE_VERSION, ('Unsupported pak file ' |
+ 'version (%d) in %s. Only ' |
+ 'support version %d' % |
+ (version, pak_file, PAK_FILE_VERSION)) |
+ if num_entries > 0: |
+ # Read the index and data. |
+ data = data[HEADER_LENGTH:] |
+ for _ in range(num_entries): |
+ resource_id, offset = struct.unpack('<HI', data[:INDEX_ENTRY_SIZE]) |
+ data = data[INDEX_ENTRY_SIZE:] |
+ _next_id, next_offset = struct.unpack('<HI', data[:INDEX_ENTRY_SIZE]) |
+ resource_size = next_offset - offset |
+ |
+ symbol_name = GetReadablePakResourceName(pak_file, resource_id) |
+ symbol_path = pak_file |
+ symbol_type = 'd' # Data. Approximation. |
+ symbol_size = resource_size |
+ symbols.append((symbol_name, symbol_type, symbol_size, symbol_path)) |
+ |
def _find_in_system_path(binary): |
"""Locate the full path to binary in the system path or return None |
if not found.""" |
@@ -726,6 +793,9 @@ def main(): |
parser.add_option('--library', metavar='PATH', |
help='if specified, process symbols in the library at ' |
'the specified path. Mutually exclusive with --nm-in.') |
+ parser.add_option('--pak', metavar='PATH', |
+ help='if specified, includes the contents of the ' |
+ 'specified *.pak file in the output.') |
parser.add_option('--nm-binary', |
help='use the specified nm binary to analyze library. ' |
'This is to be used when the nm in the path is not for ' |
@@ -796,6 +866,9 @@ def main(): |
assert nm_binary, 'Unable to find nm in the path. Use --nm-binary '\ |
'to specify location.' |
+ if opts.pak: |
+ assert os.path.isfile(opts.pak), 'Could not find ' % opts.pak |
+ |
print('addr2line: %s' % addr2line_binary) |
print('nm: %s' % nm_binary) |
@@ -806,6 +879,10 @@ def main(): |
addr2line_binary, nm_binary, |
opts.disable_disambiguation is None, |
opts.source_path) |
+ |
+ if opts.pak: |
+ AddPakData(symbols, opts.pak) |
+ |
if not os.path.exists(opts.destdir): |
os.makedirs(opts.destdir, 0755) |