tools/binary_size/libsupersize/nm.py
def CreateUniqueSymbols(elf_path, tool_prefix, section_ranges):
  """Creates symbols from nm --print-size output.

  Creates only one symbol for each address (does not create symbol aliases).
  """
  # Filter to sections we care about and sort by (address, size).
  section_ranges = [
      x for x in section_ranges.items() if x[0] in models.NATIVE_SECTIONS
  ]
  section_ranges.sort(key=lambda x: x[1])
  min_address = section_ranges[0][1][0]
  max_address = sum(section_ranges[-1][1])

  args = [
      path_util.GetNmPath(tool_prefix), '--no-sort', '--defined-only',
      '--print-size', elf_path
  ]
  # pylint: disable=unexpected-keyword-arg
  stdout = subprocess.check_output(args,
                                   stderr=subprocess.DEVNULL,
                                   encoding='utf-8')
  lines = stdout.splitlines()
  logging.debug('Parsing %d lines of output', len(lines))
  symbols_by_address = {}
  # Example 32-bit output:
  # 00857f94 00000004 t __on_dlclose_late
  # 000001ec r ndk_build_number
  for line in lines:
    tokens = line.split(' ', 3)
    num_tokens = len(tokens)
    if num_tokens < 3:
      # Address with no size and no name.
      continue
    address_str = tokens[0]
    # Check if size is omitted (can happen with binutils but not llvm).
    if num_tokens == 3:
      size_str = '0'
      section = tokens[1]
      mangled_name = tokens[2]
    else:
      size_str = tokens[1]
      section = tokens[2]
      mangled_name = tokens[3]

    if section not in 'BbDdTtRrWw' or not _IsRelevantNmName(mangled_name):
      continue

    address = int(address_str, 16)

    # Ignore symbols outside of sections that we care about.
    # Symbols can still exist in sections that we do not care about if those
    # sections are interleaved. We discard such symbols in the next loop.
    if not min_address <= address < max_address:
      continue

    # Pick the alias that defines a size.
    existing_alias = symbols_by_address.get(address)
    if existing_alias and existing_alias.size > 0:
      continue

    size = int(size_str, 16)

    # E.g.: .str.2.llvm.12282370934750212
    if mangled_name.startswith('.str.'):
      mangled_name = models.STRING_LITERAL_NAME
    elif mangled_name.startswith('__ARMV7PILongThunk_'):
      # Convert thunks from prefix to suffix so that name is demangleable.
      mangled_name = mangled_name[len('__ARMV7PILongThunk_'):] + '.LongThunk'
    elif mangled_name.startswith('__ThumbV7PILongThunk_'):
      mangled_name = mangled_name[len('__ThumbV7PILongThunk_'):] + '.LongThunk'

    # Use address (next loop) to determine between .data and .data.rel.ro.
    section_name = None
    if section in 'Tt':
      section_name = models.SECTION_TEXT
    elif section in 'Rr':
      section_name = models.SECTION_RODATA
    elif section in 'Bb':
      section_name = models.SECTION_BSS

    # No need to demangle names since they will be demangled by
    # DemangleRemainingSymbols().
    symbols_by_address[address] = models.Symbol(section_name,
                                                size,
                                                address=address,
                                                full_name=mangled_name)

  logging.debug('Sorting %d NM symbols', len(symbols_by_address))
  # Sort symbols by address.
  sorted_symbols = sorted(symbols_by_address.values(), key=lambda s: s.address)

  # Assign section to symbols based on address, and size where unspecified.
  # Use address rather than nm's section character to distinguish between
  # .data.rel.ro and .data.
  logging.debug('Assigning section_name and filling in missing sizes')
  section_range_iter = iter(section_ranges)
  section_end = -1
  raw_symbols = []
  active_assembly_sym = None
  for i, sym in enumerate(sorted_symbols):
    # Move to next section if applicable.
    while sym.address >= section_end:
      section_range = next(section_range_iter)
      section_name, (section_start, section_size) = section_range
      section_end = section_start + section_size

    # Skip symbols that don't fall into a section that we care about
    # (e.g. GCC_except_table533 from .eh_frame).
    if sym.address < section_start:
      continue

    if sym.section_name and sym.section_name != section_name:
      logging.warning('Re-assigning section for %r to %s', sym, section_name)
    sym.section_name = section_name

    if i + 1 < len(sorted_symbols):
      next_addr = sorted_symbols[i + 1].address
    else:
      next_addr = section_end

    # Heuristic: Discard subsequent assembly symbols (no size) that are ALL_CAPS
    # or .-prefixed, since they are likely labels within a function.
    if (active_assembly_sym and sym.size == 0
        and sym.section_name == models.SECTION_TEXT):
      if sym.full_name.startswith('.') or sym.full_name.isupper():
        active_assembly_sym.size += next_addr - sym.address
        # Triggers ~30 times for all of libchrome.so.
        logging.debug('Discarding assembly label: %s', sym.full_name)
        continue

    active_assembly_sym = sym if sym.size == 0 else None

    # For assembly symbols:
    # Add in a size when absent and guard against size overlapping next symbol.
    if active_assembly_sym or sym.end_address > next_addr:
      sym.size = next_addr - sym.address

    raw_symbols.append(sym)

  return raw_symbols
Creates symbols from nm --print-size output.

  Creates only one symbol for each address (does not create symbol aliases).
  
Creates symbols from nm --print-size output.
Creates only one symbol for each address (does not create symbol aliases).
Creates symbols from nm -- print - size output . Creates only one symbol for each address ( does not create symbol aliases ) .
def CreateUniqueSymbols(elf_path, tool_prefix, section_ranges):
  section_ranges = [
      x for x in section_ranges.items() if x[0] in models.NATIVE_SECTIONS
  ]
  section_ranges.sort(key=lambda x: x[1])
  min_address = section_ranges[0][1][0]
  max_address = sum(section_ranges[-1][1])
  args = [
      path_util.GetNmPath(tool_prefix), '--no-sort', '--defined-only',
      '--print-size', elf_path
  ]
  stdout = subprocess.check_output(args,
                                   stderr=subprocess.DEVNULL,
                                   encoding='utf-8')
  lines = stdout.splitlines()
  logging.debug('Parsing %d lines of output', len(lines))
  symbols_by_address = {}
  for line in lines:
    tokens = line.split(' ', 3)
    num_tokens = len(tokens)
    if num_tokens < 3:
      continue
    address_str = tokens[0]
    if num_tokens == 3:
      size_str = '0'
      section = tokens[1]
      mangled_name = tokens[2]
    else:
      size_str = tokens[1]
      section = tokens[2]
      mangled_name = tokens[3]
    if section not in 'BbDdTtRrWw' or not _IsRelevantNmName(mangled_name):
      continue
    address = int(address_str, 16)
    if not min_address <= address < max_address:
      continue
    existing_alias = symbols_by_address.get(address)
    if existing_alias and existing_alias.size > 0:
      continue
    size = int(size_str, 16)
    if mangled_name.startswith('.str.'):
      mangled_name = models.STRING_LITERAL_NAME
    elif mangled_name.startswith('__ARMV7PILongThunk_'):
      mangled_name = mangled_name[len('__ARMV7PILongThunk_'):] + '.LongThunk'
    elif mangled_name.startswith('__ThumbV7PILongThunk_'):
      mangled_name = mangled_name[len('__ThumbV7PILongThunk_'):] + '.LongThunk'
    section_name = None
    if section in 'Tt':
      section_name = models.SECTION_TEXT
    elif section in 'Rr':
      section_name = models.SECTION_RODATA
    elif section in 'Bb':
      section_name = models.SECTION_BSS
    symbols_by_address[address] = models.Symbol(section_name,
                                                size,
                                                address=address,
                                                full_name=mangled_name)
  logging.debug('Sorting %d NM symbols', len(symbols_by_address))
  sorted_symbols = sorted(symbols_by_address.values(), key=lambda s: s.address)
  logging.debug('Assigning section_name and filling in missing sizes')
  section_range_iter = iter(section_ranges)
  section_end = -1
  raw_symbols = []
  active_assembly_sym = None
  for i, sym in enumerate(sorted_symbols):
    while sym.address >= section_end:
      section_range = next(section_range_iter)
      section_name, (section_start, section_size) = section_range
      section_end = section_start + section_size
    if sym.address < section_start:
      continue
    if sym.section_name and sym.section_name != section_name:
      logging.warning('Re-assigning section for %r to %s', sym, section_name)
    sym.section_name = section_name
    if i + 1 < len(sorted_symbols):
      next_addr = sorted_symbols[i + 1].address
    else:
      next_addr = section_end
    if (active_assembly_sym and sym.size == 0
        and sym.section_name == models.SECTION_TEXT):
      if sym.full_name.startswith('.') or sym.full_name.isupper():
        active_assembly_sym.size += next_addr - sym.address
        logging.debug('Discarding assembly label: %s', sym.full_name)
        continue
    active_assembly_sym = sym if sym.size == 0 else None
    if active_assembly_sym or sym.end_address > next_addr:
      sym.size = next_addr - sym.address
    raw_symbols.append(sym)
  return raw_symbols
def CreateUniqueSymbols ( elf_path , tool_prefix , section_ranges ) : section_ranges = [ x for x in section_ranges . items ( ) if x [ 0 ] in models . NATIVE_SECTIONS ] section_ranges . sort ( key = lambda x : x [ 1 ] ) min_address = section_ranges [ 0 ] [ 1 ] [ 0 ] max_address = sum ( section_ranges [ - 1 ] [ 1 ] ) args = [ path_util . GetNmPath ( tool_prefix ) , '--no-sort' , '--defined-only' , '--print-size' , elf_path ] stdout = subprocess . check_output ( args , stderr = subprocess . DEVNULL , encoding = 'utf-8' ) lines = stdout . splitlines ( ) logging . debug ( 'Parsing %d lines of output' , len ( lines ) ) symbols_by_address = { } for line in lines : tokens = line . split ( ' ' , 3 ) num_tokens = len ( tokens ) if num_tokens < 3 : continue address_str = tokens [ 0 ] if num_tokens == 3 : size_str = '0' section = tokens [ 1 ] mangled_name = tokens [ 2 ] else : size_str = tokens [ 1 ] section = tokens [ 2 ] mangled_name = tokens [ 3 ] if section not in 'BbDdTtRrWw' or not _IsRelevantNmName ( mangled_name ) : continue address = int ( address_str , 16 ) if not min_address <= address < max_address : continue existing_alias = symbols_by_address . get ( address ) if existing_alias and existing_alias . size > 0 : continue size = int ( size_str , 16 ) if mangled_name . startswith ( '.str.' ) : mangled_name = models . STRING_LITERAL_NAME elif mangled_name . startswith ( '__ARMV7PILongThunk_' ) : mangled_name = mangled_name [ len ( '__ARMV7PILongThunk_' ) : ] + '.LongThunk' elif mangled_name . startswith ( '__ThumbV7PILongThunk_' ) : mangled_name = mangled_name [ len ( '__ThumbV7PILongThunk_' ) : ] + '.LongThunk' section_name = None if section in 'Tt' : section_name = models . SECTION_TEXT elif section in 'Rr' : section_name = models . SECTION_RODATA elif section in 'Bb' : section_name = models . SECTION_BSS symbols_by_address [ address ] = models . Symbol ( section_name , size , address = address , full_name = mangled_name ) logging . debug ( 'Sorting %d NM symbols' , len ( symbols_by_address ) ) sorted_symbols = sorted ( symbols_by_address . values ( ) , key = lambda s : s . address ) logging . debug ( 'Assigning section_name and filling in missing sizes' ) section_range_iter = iter ( section_ranges ) section_end = - 1 raw_symbols = [ ] active_assembly_sym = None for i , sym in enumerate ( sorted_symbols ) : while sym . address >= section_end : section_range = next ( section_range_iter ) section_name , ( section_start , section_size ) = section_range section_end = section_start + section_size if sym . address < section_start : continue if sym . section_name and sym . section_name != section_name : logging . warning ( 'Re-assigning section for %r to %s' , sym , section_name ) sym . section_name = section_name if i + 1 < len ( sorted_symbols ) : next_addr = sorted_symbols [ i + 1 ] . address else : next_addr = section_end if ( active_assembly_sym and sym . size == 0 and sym . section_name == models . SECTION_TEXT ) : if sym . full_name . startswith ( '.' ) or sym . full_name . isupper ( ) : active_assembly_sym . size += next_addr - sym . address logging . debug ( 'Discarding assembly label: %s' , sym . full_name ) continue active_assembly_sym = sym if sym . size == 0 else None if active_assembly_sym or sym . end_address > next_addr : sym . size = next_addr - sym . address raw_symbols . append ( sym ) return raw_symbols
Creates symbols from nm --print-size output.
Creates symbols from nm -- print - size output .
"""Creates symbols from nm --print-size output.

  Creates only one symbol for each address (does not create symbol aliases).
  """ # Filter to sections we care about and sort by (address, size). # pylint: disable=unexpected-keyword-arg # Example 32-bit output: # 00857f94 00000004 t __on_dlclose_late # 000001ec r ndk_build_number # Address with no size and no name. # Check if size is omitted (can happen with binutils but not llvm). # Ignore symbols outside of sections that we care about. # Symbols can still exist in sections that we do not care about if those # sections are interleaved. We discard such symbols in the next loop. # Pick the alias that defines a size. # E.g.: .str.2.llvm.12282370934750212 # Convert thunks from prefix to suffix so that name is demangleable. # Use address (next loop) to determine between .data and .data.rel.ro. # No need to demangle names since they will be demangled by # DemangleRemainingSymbols(). # Sort symbols by address. # Assign section to symbols based on address, and size where unspecified. # Use address rather than nm's section character to distinguish between # .data.rel.ro and .data. # Move to next section if applicable. # Skip symbols that don't fall into a section that we care about # (e.g. GCC_except_table533 from .eh_frame). # Heuristic: Discard subsequent assembly symbols (no size) that are ALL_CAPS # or .-prefixed, since they are likely labels within a function. # Triggers ~30 times for all of libchrome.so. # For assembly symbols: # Add in a size when absent and guard against size overlapping next symbol.
elf_path
tool_prefix
section_ranges