910e62b5创建于 1月15日历史提交
# Copyright 2025 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Shared utilities for orderfile generation."""

from typing import Optional
import android_profile_tool
import cluster
import process_profiles


def ReadNonEmptyStrippedFromFile(file_name):
  """Reads a file, strips leading/trailing whitespace and removes empty lines.
  """
  stripped_lines = []
  with open(file_name, 'r') as file:
    for line in file:
      stripped_line = line.strip()
      if stripped_line:
        stripped_lines.append(stripped_line)
  return stripped_lines


def AddDummyFunctions(unpatched_orderfile_path, orderfile_path):
  """Adds dummy functions to the orderfile."""
  symbols = ReadNonEmptyStrippedFromFile(unpatched_orderfile_path)
  with open(orderfile_path, 'w') as f:
    # Make sure the anchor functions are located in the right place, here and
    # after everything else.
    # See the comment in //base/android/library_loader/anchor_functions.cc.
    f.write('dummy_function_start_of_ordered_text\n')
    f.writelines(s + '\n' for s in symbols)
    f.write('dummy_function_end_of_ordered_text\n')


def ProcessProfiles(profile_files, lib_chrome_so_path):
  """Processes profiles to get an ordered list of symbols."""
  profiles = process_profiles.ProfileManager(profile_files)
  processor = process_profiles.SymbolOffsetProcessor(lib_chrome_so_path)
  ordered_symbols = cluster.ClusterOffsets(profiles, processor)
  if not ordered_symbols:
    raise Exception('Failed to get ordered symbols')
  for sym in ordered_symbols:
    assert not sym.startswith('OUTLINED_FUNCTION_'), (
        'Outlined function found in instrumented function, very likely '
        'something has gone very wrong!')
  symbols_size = processor.SymbolsSize(ordered_symbols)
  return ordered_symbols, symbols_size


def CollectProfiles(profiler: android_profile_tool.AndroidProfileTool,
                    profile_webview: bool,
                    arch: str,
                    apk_path_or_browser_name: str,
                    out_dir_str: Optional[str] = None,
                    webview_installer_path: Optional[str] = None):
  """Collects profiles from the device."""
  if profile_webview:
    if not webview_installer_path:
      raise ValueError(
          'webview_installer_path must be provided for webview profiling')
    profiler.InstallAndSetWebViewProvider(webview_installer_path)
    return profiler.CollectWebViewStartupProfile(apk_path_or_browser_name,
                                                 arch, out_dir_str)

  if arch == 'arm64':
    return profiler.CollectSpeedometerProfile(apk_path_or_browser_name,
                                              out_dir_str)
  return profiler.CollectSystemHealthProfile(apk_path_or_browser_name,
                                             out_dir_str)


def GetLibchromeSoPath(out_dir, arch, profile_webview=False):
  """Returns the path to the unstripped libmonochrome.so."""
  libchrome_target = GetLibchromeTarget(arch, profile_webview)
  return str(out_dir / f'lib.unstripped/{libchrome_target}.so')


def GetLibchromeTarget(arch, profile_webview=False):
  """Returns the libmonochrome target name."""
  if profile_webview:
    return 'libwebviewchromium'
  target = 'libmonochrome'
  if '64' in arch:
    # Trichrome has a _64 suffix for arm64 and x64 builds.
    target += '_64'
  return target


def AddCommonArguments(parser):
  """Adds common arguments to the parser."""
  parser.add_argument('--target-arch',
                      dest='arch',
                      required=True,
                      choices=['arm', 'arm64', 'x86', 'x64'],
                      help='The target architecture for which to build.')
  parser.add_argument('--profile-webview',
                      action='store_true',
                      default=False,
                      help='Use the WebView benchmark profiles to generate the '
                      'orderfile.')
  parser.add_argument('--streamline-for-debugging',
                      action='store_true',
                      help=('Streamline the run for faster debugging.'))
  parser.add_argument('-v',
                      '--verbose',
                      dest='verbosity',
                      action='count',
                      default=0,
                      help='Increase verbosity for debugging.')
  parser.add_argument('--save-profile-data',
                      action='store_true',
                      default=False,
                      help='Avoid deleting the generated profile data.')