Home | History | Annotate | Download | only in resources
      1 # Copyright 2014 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Common utilities for tools that deal with binary size information.
      6 
      7 Copied from chromium/src/build/android/pylib/symbols/binary_size_tools.py.
      8 """
      9 
     10 import logging
     11 import re
     12 
     13 
     14 def ParseNm(nm_lines):
     15   """Parse nm output, returning data for all relevant (to binary size)
     16   symbols and ignoring the rest.
     17 
     18   Args:
     19       nm_lines: an iterable over lines of nm output.
     20 
     21   Yields:
     22       (symbol name, symbol type, symbol size, source file path).
     23 
     24       Path may be None if nm couldn't figure out the source file.
     25   """
     26 
     27   # Match lines with size, symbol, optional location, optional discriminator
     28   sym_re = re.compile(r'^[0-9a-f]{8,} ' # address (8+ hex digits)
     29                       '([0-9a-f]{8,}) ' # size (8+ hex digits)
     30                       '(.) ' # symbol type, one character
     31                       '([^\t]+)' # symbol name, separated from next by tab
     32                       '(?:\t(.*):[\d\?]+)?.*$') # location
     33   # Match lines with addr but no size.
     34   addr_re = re.compile(r'^[0-9a-f]{8,} (.) ([^\t]+)(?:\t.*)?$')
     35   # Match lines that don't have an address at all -- typically external symbols.
     36   noaddr_re = re.compile(r'^ {8,} (.) (.*)$')
     37   # Match lines with no symbol name, only addr and type
     38   addr_only_re = re.compile(r'^[0-9a-f]{8,} (.)$')
     39 
     40   for line in nm_lines:
     41     line = line.rstrip()
     42     match = sym_re.match(line)
     43     if match:
     44       size, sym_type, sym = match.groups()[0:3]
     45       size = int(size, 16)
     46       if sym_type in ('B', 'b'):
     47         continue  # skip all BSS for now.
     48       path = match.group(4)
     49       yield sym, sym_type, size, path
     50       continue
     51     match = addr_re.match(line)
     52     if match:
     53       # sym_type, sym = match.groups()[0:2]
     54       continue  # No size == we don't care.
     55     match = noaddr_re.match(line)
     56     if match:
     57       sym_type, sym = match.groups()
     58       if sym_type in ('U', 'w'):
     59         continue  # external or weak symbol
     60     match = addr_only_re.match(line)
     61     if match:
     62       continue  # Nothing to do.
     63 
     64 
     65     # If we reach this part of the loop, there was something in the
     66     # line that we didn't expect or recognize.
     67     logging.warning('nm output parser failed to parse: %s', repr(line))
     68