コード例 #1
0
def Run(args, parser):
  if not args.size_file.endswith('.size'):
    parser.error('size_file must end with .size')

  (output_directory, tool_prefix, apk_path, apk_so_path, elf_path, map_path) = (
      DeduceMainPaths(args, parser))

  metadata = CreateMetadata(map_path, elf_path, apk_path, tool_prefix,
                            output_directory)

  apk_elf_result = None
  if apk_path and elf_path:
    # Extraction takes around 1 second, so do it in parallel.
    apk_elf_result = concurrent.ForkAndCall(
        _ElfInfoFromApk, (apk_path, apk_so_path, tool_prefix))

  section_sizes, raw_symbols = CreateSectionSizesAndSymbols(
      map_path=map_path, tool_prefix=tool_prefix, elf_path=elf_path,
      apk_path=apk_path, output_directory=output_directory,
      track_string_literals=args.track_string_literals,
      metadata=metadata, apk_elf_result=apk_elf_result,
      pak_files=args.pak_file, pak_info_file=args.pak_info_file)
  size_info = CreateSizeInfo(
      section_sizes, raw_symbols, metadata=metadata, normalize_names=False)

  if logging.getLogger().isEnabledFor(logging.INFO):
    for line in describe.DescribeSizeInfoCoverage(size_info):
      logging.info(line)
  logging.info('Recorded info for %d symbols', len(size_info.raw_symbols))
  logging.info('Recording metadata: \n  %s',
               '\n  '.join(describe.DescribeMetadata(size_info.metadata)))
  logging.info('Saving result to %s', args.size_file)
  file_format.SaveSizeInfo(size_info, args.size_file)
  size_in_mb = os.path.getsize(args.size_file) / 1024.0 / 1024.0
  logging.info('Done. File size is %.2fMiB.', size_in_mb)
コード例 #2
0
ファイル: nm.py プロジェクト: tk001github/chromium
def CollectAliasesByAddressAsync(elf_path, tool_prefix):
  """Calls CollectAliasesByAddress in a helper process. Returns a Result."""
  def decode(encoded):
    return concurrent.DecodeDictOfLists(encoded, key_transform=int)
  return concurrent.ForkAndCall(
      _CollectAliasesByAddressAsyncHelper, (elf_path, tool_prefix),
      decode_func=decode)
コード例 #3
0
 def testForkAndCall_normal(self):
     parent_pid = os.getpid()
     result = concurrent.ForkAndCall(
         _ForkTestHelper, (self, parent_pid, 1, 2, Unpicklable()))
     self.assertEquals(3, result.get())
コード例 #4
0
 def testForkAndCall_exception(self):
     parent_pid = os.getpid()
     result = concurrent.ForkAndCall(_ForkTestHelper,
                                     (self, parent_pid, 1, 'a'))
     self.assertRaises(TypeError, result.get)
コード例 #5
0
def Run(args, parser):
    if not args.size_file.endswith('.size'):
        parser.error('size_file must end with .size')

    elf_path = args.elf_file
    map_path = args.map_file
    apk_path = args.apk_file
    any_input = apk_path or elf_path or map_path
    if not any_input:
        parser.error(
            'Most pass at least one of --apk-file, --elf-file, --map-file')
    lazy_paths = paths.LazyPaths(tool_prefix=args.tool_prefix,
                                 output_directory=args.output_directory,
                                 any_path_within_output_directory=any_input)
    if apk_path:
        with zipfile.ZipFile(apk_path) as z:
            lib_infos = [
                f for f in z.infolist()
                if f.filename.endswith('.so') and f.file_size > 0
            ]
        assert lib_infos, 'APK has no .so files.'
        # TODO(agrieve): Add support for multiple .so files, and take into account
        #     secondary architectures.
        apk_so_path = max(lib_infos, key=lambda x: x.file_size).filename
        logging.debug('Sub-apk path=%s', apk_so_path)
        if not elf_path and lazy_paths.output_directory:
            elf_path = os.path.join(
                lazy_paths.output_directory, 'lib.unstripped',
                os.path.basename(apk_so_path.replace('crazy.', '')))
            logging.debug('Detected --elf-file=%s', elf_path)

    if map_path:
        if not map_path.endswith('.map') and not map_path.endswith('.map.gz'):
            parser.error('Expected --map-file to end with .map or .map.gz')
    else:
        map_path = elf_path + '.map'
        if not os.path.exists(map_path):
            map_path += '.gz'
        if not os.path.exists(map_path):
            parser.error('Could not find .map(.gz)? file. Use --map-file.')

    tool_prefix = lazy_paths.VerifyToolPrefix()
    output_directory = None
    if not args.no_source_paths:
        output_directory = lazy_paths.VerifyOutputDirectory()

    metadata = CreateMetadata(map_path, elf_path, apk_path, tool_prefix,
                              output_directory)
    if apk_path and elf_path:
        # Extraction takes around 1 second, so do it in parallel.
        apk_elf_result = concurrent.ForkAndCall(
            _ElfInfoFromApk, (apk_path, apk_so_path, tool_prefix))

    size_info = CreateSizeInfo(map_path,
                               elf_path,
                               tool_prefix,
                               output_directory,
                               normalize_names=False)

    if metadata:
        size_info.metadata = metadata

        if apk_path:
            logging.debug('Extracting section sizes from .so within .apk')
            unstripped_section_sizes = size_info.section_sizes
            apk_build_id, size_info.section_sizes = apk_elf_result.get()
            assert apk_build_id == metadata[models.METADATA_ELF_BUILD_ID], (
                'BuildID for %s within %s did not match the one at %s' %
                (apk_so_path, apk_path, elf_path))

            packed_section_name = None
            architecture = metadata[models.METADATA_ELF_ARCHITECTURE]
            # Packing occurs enabled only arm32 & arm64.
            if architecture == 'arm':
                packed_section_name = '.rel.dyn'
            elif architecture == 'arm64':
                packed_section_name = '.rela.dyn'

            if packed_section_name:
                logging.debug('Recording size of unpacked relocations')
                if packed_section_name not in size_info.section_sizes:
                    logging.warning('Packed section not present: %s',
                                    packed_section_name)
                else:
                    size_info.section_sizes[
                        '%s (unpacked)' % packed_section_name] = (
                            unstripped_section_sizes.get(packed_section_name))

    logging.info('Recording metadata: \n  %s',
                 '\n  '.join(describe.DescribeMetadata(size_info.metadata)))
    logging.info('Saving result to %s', args.size_file)
    file_format.SaveSizeInfo(size_info, args.size_file)
    logging.info('Done')
コード例 #6
0
def CreateSectionSizesAndSymbols(
      map_path=None, tool_prefix=None, output_directory=None, elf_path=None,
      apk_path=None, track_string_literals=True, metadata=None,
      apk_so_path=None, pak_files=None, pak_info_file=None,
      knobs=SectionSizeKnobs()):
  """Creates sections sizes and symbols for a SizeInfo.

  Args:
    map_path: Path to the linker .map(.gz) file to parse.
    elf_path: Path to the corresponding unstripped ELF file. Used to find symbol
        aliases and inlined functions. Can be None.
    tool_prefix: Prefix for c++filt & nm (required).
    output_directory: Build output directory. If None, source_paths and symbol
        alias information will not be recorded.
    track_string_literals: Whether to break down "** merge string" sections into
        smaller symbols (requires output_directory).
  """
  if apk_path and elf_path:
    # Extraction takes around 1 second, so do it in parallel.
    apk_elf_result = concurrent.ForkAndCall(
        _ElfInfoFromApk, (apk_path, apk_so_path, tool_prefix))

  source_mapper = None
  elf_object_paths = None
  if output_directory:
    # Start by finding the elf_object_paths, so that nm can run on them while
    # the linker .map is being parsed.
    logging.info('Parsing ninja files.')
    source_mapper, elf_object_paths = ninja_parser.Parse(
        output_directory, elf_path)
    logging.debug('Parsed %d .ninja files.', source_mapper.parsed_file_count)
    assert not elf_path or elf_object_paths, (
        'Failed to find link command in ninja files for ' +
        os.path.relpath(elf_path, output_directory))

  section_sizes, raw_symbols = _ParseElfInfo(
      map_path, elf_path, tool_prefix, output_directory, track_string_literals,
      elf_object_paths)
  elf_overhead_size = _CalculateElfOverhead(section_sizes, elf_path)

  pak_symbols_by_id = None
  if apk_path:
    pak_symbols_by_id = _FindPakSymbolsFromApk(apk_path, output_directory,
                                               knobs)
    if elf_path:
      section_sizes, elf_overhead_size = _ParseApkElfSectionSize(
          section_sizes, metadata, apk_elf_result)
    raw_symbols.extend(
        _ParseDexSymbols(section_sizes, apk_path, output_directory))
    raw_symbols.extend(
        _ParseApkOtherSymbols(section_sizes, apk_path, apk_so_path))
  elif pak_files and pak_info_file:
    pak_symbols_by_id = _FindPakSymbolsFromFiles(
        pak_files, pak_info_file, output_directory)

  if elf_path:
    elf_overhead_symbol = models.Symbol(
        models.SECTION_OTHER, elf_overhead_size, full_name='Overhead: ELF file')
    prev = section_sizes.setdefault(models.SECTION_OTHER, 0)
    section_sizes[models.SECTION_OTHER] = prev + elf_overhead_size
    raw_symbols.append(elf_overhead_symbol)

  if pak_symbols_by_id:
    object_paths = (p for p in source_mapper.IterAllPaths() if p.endswith('.o'))
    pak_raw_symbols = _ParsePakSymbols(
        section_sizes, object_paths, output_directory, pak_symbols_by_id)
    raw_symbols.extend(pak_raw_symbols)

  _ExtractSourcePathsAndNormalizeObjectPaths(raw_symbols, source_mapper)
  logging.info('Converting excessive aliases into shared-path symbols')
  _CompactLargeAliasesIntoSharedSymbols(raw_symbols, knobs)
  logging.debug('Connecting nm aliases')
  _ConnectNmAliases(raw_symbols)
  return section_sizes, raw_symbols
コード例 #7
0
ファイル: archive.py プロジェクト: jingbanghu/chromium
def Run(args, parser):
  if not args.size_file.endswith('.size'):
    parser.error('size_file must end with .size')

  elf_path = args.elf_file
  map_path = args.map_file
  apk_path = args.apk_file
  pak_files = args.pak_file
  pak_info_file = args.pak_info_file
  any_input = apk_path or elf_path or map_path
  if not any_input:
    parser.error('Most pass at least one of --apk-file, --elf-file, --map-file')
  output_directory_finder = path_util.OutputDirectoryFinder(
      value=args.output_directory,
      any_path_within_output_directory=any_input)
  if apk_path:
    with zipfile.ZipFile(apk_path) as z:
      lib_infos = [f for f in z.infolist()
                   if f.filename.endswith('.so') and f.file_size > 0]
    assert lib_infos, 'APK has no .so files.'
    # TODO(agrieve): Add support for multiple .so files, and take into account
    #     secondary architectures.
    apk_so_path = max(lib_infos, key=lambda x:x.file_size).filename
    logging.debug('Sub-apk path=%s', apk_so_path)
    if not elf_path and output_directory_finder.Tentative():
      elf_path = os.path.join(
          output_directory_finder.Tentative(), 'lib.unstripped',
          os.path.basename(apk_so_path.replace('crazy.', '')))
      logging.debug('Detected --elf-file=%s', elf_path)

  if map_path:
    if not map_path.endswith('.map') and not map_path.endswith('.map.gz'):
      parser.error('Expected --map-file to end with .map or .map.gz')
  else:
    map_path = elf_path + '.map'
    if not os.path.exists(map_path):
      map_path += '.gz'
    if not os.path.exists(map_path):
      parser.error('Could not find .map(.gz)? file. Ensure you have built with '
                   'is_official_build=true, or use --map-file to point me a '
                   'linker map file.')

  linker_name = _DetectLinkerName(map_path)
  tool_prefix_finder = path_util.ToolPrefixFinder(
      value=args.tool_prefix,
      output_directory_finder=output_directory_finder,
      linker_name=linker_name)
  tool_prefix = tool_prefix_finder.Finalized()
  output_directory = None
  if not args.no_source_paths:
    output_directory = output_directory_finder.Finalized()

  metadata = CreateMetadata(map_path, elf_path, apk_path, tool_prefix,
                            output_directory)
  if apk_path and elf_path:
    # Extraction takes around 1 second, so do it in parallel.
    apk_elf_result = concurrent.ForkAndCall(
        _ElfInfoFromApk, (apk_path, apk_so_path, tool_prefix))

  section_sizes, raw_symbols = CreateSectionSizesAndSymbols(
      map_path, elf_path, tool_prefix, output_directory,
      track_string_literals=args.track_string_literals)
  if apk_path:
    AddApkInfo(section_sizes, raw_symbols, apk_path, output_directory,
               metadata, apk_elf_result)
  elif pak_files and pak_info_file:
    AddPakSymbolsFromFiles(
        section_sizes, raw_symbols, pak_files, pak_info_file)
  size_info = CreateSizeInfo(
      section_sizes, raw_symbols, metadata=metadata, normalize_names=False)

  if logging.getLogger().isEnabledFor(logging.INFO):
    for line in describe.DescribeSizeInfoCoverage(size_info):
      logging.info(line)
  logging.info('Recorded info for %d symbols', len(size_info.raw_symbols))
  logging.info('Recording metadata: \n  %s',
               '\n  '.join(describe.DescribeMetadata(size_info.metadata)))
  logging.info('Saving result to %s', args.size_file)
  file_format.SaveSizeInfo(size_info, args.size_file)
  size_in_mb = os.path.getsize(args.size_file) / 1024.0 / 1024.0
  logging.info('Done. File size is %.2fMiB.', size_in_mb)