Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Unified Diff: tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper.py

Issue 1647513002: Delete tools/telemetry. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper.py
diff --git a/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper.py b/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper.py
deleted file mode 100644
index 3fddf923c7166d96eb6a5a8d8f91f5eb8d8a9992..0000000000000000000000000000000000000000
--- a/tools/telemetry/telemetry/internal/platform/profiler/android_profiling_helper.py
+++ /dev/null
@@ -1,311 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import glob
-import hashlib
-import logging
-import os
-import platform
-import re
-import shutil
-import subprocess
-
-from telemetry.internal.util import binary_manager
-from telemetry.core import platform as telemetry_platform
-from telemetry.core import util
-from telemetry import decorators
-from telemetry.internal.platform.profiler import android_prebuilt_profiler_helper
-
-from devil.android import md5sum # pylint: disable=import-error
-
-
-try:
- import sqlite3
-except ImportError:
- sqlite3 = None
-
-
-
-_TEXT_SECTION = '.text'
-
-
-def _ElfMachineId(elf_file):
- headers = subprocess.check_output(['readelf', '-h', elf_file])
- return re.match(r'.*Machine:\s+(\w+)', headers, re.DOTALL).group(1)
-
-
-def _ElfSectionAsString(elf_file, section):
- return subprocess.check_output(['readelf', '-p', section, elf_file])
-
-
-def _ElfSectionMd5Sum(elf_file, section):
- result = subprocess.check_output(
- 'readelf -p%s "%s" | md5sum' % (section, elf_file), shell=True)
- return result.split(' ', 1)[0]
-
-
-def _FindMatchingUnstrippedLibraryOnHost(device, lib):
- lib_base = os.path.basename(lib)
-
- device_md5 = device.RunShellCommand('md5 "%s"' % lib, as_root=True)[0]
- device_md5 = device_md5.split(' ', 1)[0]
-
- def FindMatchingStrippedLibrary(out_path):
- # First find a matching stripped library on the host. This avoids the need
- # to pull the stripped library from the device, which can take tens of
- # seconds.
- host_lib_pattern = os.path.join(out_path, '*_apk', 'libs', '*', lib_base)
- for stripped_host_lib in glob.glob(host_lib_pattern):
- with open(stripped_host_lib) as f:
- host_md5 = hashlib.md5(f.read()).hexdigest()
- if host_md5 == device_md5:
- return stripped_host_lib
-
- for build_dir, build_type in util.GetBuildDirectories():
- out_path = os.path.join(build_dir, build_type)
- stripped_host_lib = FindMatchingStrippedLibrary(out_path)
- if stripped_host_lib:
- break
- else:
- return None
-
- # The corresponding unstripped library will be under out/Release/lib.
- unstripped_host_lib = os.path.join(out_path, 'lib', lib_base)
-
- # Make sure the unstripped library matches the stripped one. We do this
- # by comparing the hashes of text sections in both libraries. This isn't an
- # exact guarantee, but should still give reasonable confidence that the
- # libraries are compatible.
- # TODO(skyostil): Check .note.gnu.build-id instead once we're using
- # --build-id=sha1.
- # pylint: disable=undefined-loop-variable
- if (_ElfSectionMd5Sum(unstripped_host_lib, _TEXT_SECTION) !=
- _ElfSectionMd5Sum(stripped_host_lib, _TEXT_SECTION)):
- return None
- return unstripped_host_lib
-
-
-@decorators.Cache
-def GetPerfhostName():
- return 'perfhost_' + telemetry_platform.GetHostPlatform().GetOSVersionName()
-
-
-# Ignored directories for libraries that aren't useful for symbolization.
-_IGNORED_LIB_PATHS = [
- '/data/dalvik-cache',
- '/tmp'
-]
-
-
-def GetRequiredLibrariesForPerfProfile(profile_file):
- """Returns the set of libraries necessary to symbolize a given perf profile.
-
- Args:
- profile_file: Path to perf profile to analyse.
-
- Returns:
- A set of required library file names.
- """
- with open(os.devnull, 'w') as dev_null:
- perfhost_path = binary_manager.FetchPath(
- GetPerfhostName(), 'x86_64', 'linux')
- perf = subprocess.Popen([perfhost_path, 'script', '-i', profile_file],
- stdout=dev_null, stderr=subprocess.PIPE)
- _, output = perf.communicate()
- missing_lib_re = re.compile(
- ('^Failed to open (.*), continuing without symbols|'
- '^(.*[.]so).*not found, continuing without symbols'))
- libs = set()
- for line in output.split('\n'):
- lib = missing_lib_re.match(line)
- if lib:
- lib = lib.group(1) or lib.group(2)
- path = os.path.dirname(lib)
- if (any(path.startswith(ignored_path)
- for ignored_path in _IGNORED_LIB_PATHS)
- or path == '/' or not path):
- continue
- libs.add(lib)
- return libs
-
-
-def GetRequiredLibrariesForVTuneProfile(profile_file):
- """Returns the set of libraries necessary to symbolize a given VTune profile.
-
- Args:
- profile_file: Path to VTune profile to analyse.
-
- Returns:
- A set of required library file names.
- """
- db_file = os.path.join(profile_file, 'sqlite-db', 'dicer.db')
- conn = sqlite3.connect(db_file)
-
- try:
- # The 'dd_module_file' table lists all libraries on the device. Only the
- # ones with 'bin_located_path' are needed for the profile.
- query = 'SELECT bin_path, bin_located_path FROM dd_module_file'
- return set(row[0] for row in conn.cursor().execute(query) if row[1])
- finally:
- conn.close()
-
-
-def _FileMetadataMatches(filea, fileb):
- """Check if the metadata of two files matches."""
- assert os.path.exists(filea)
- if not os.path.exists(fileb):
- return False
-
- fields_to_compare = [
- 'st_ctime', 'st_gid', 'st_mode', 'st_mtime', 'st_size', 'st_uid']
-
- filea_stat = os.stat(filea)
- fileb_stat = os.stat(fileb)
- for field in fields_to_compare:
- # shutil.copy2 doesn't get ctime/mtime identical when the file system
- # provides sub-second accuracy.
- if int(getattr(filea_stat, field)) != int(getattr(fileb_stat, field)):
- return False
- return True
-
-
-def CreateSymFs(device, symfs_dir, libraries, use_symlinks=True):
- """Creates a symfs directory to be used for symbolizing profiles.
-
- Prepares a set of files ("symfs") to be used with profilers such as perf for
- converting binary addresses into human readable function names.
-
- Args:
- device: DeviceUtils instance identifying the target device.
- symfs_dir: Path where the symfs should be created.
- libraries: Set of library file names that should be included in the symfs.
- use_symlinks: If True, link instead of copy unstripped libraries into the
- symfs. This will speed up the operation, but the resulting symfs will no
- longer be valid if the linked files are modified, e.g., by rebuilding.
-
- Returns:
- The absolute path to the kernel symbols within the created symfs.
- """
- logging.info('Building symfs into %s.' % symfs_dir)
-
- for lib in libraries:
- device_dir = os.path.dirname(lib)
- output_dir = os.path.join(symfs_dir, device_dir[1:])
- if not os.path.exists(output_dir):
- os.makedirs(output_dir)
- output_lib = os.path.join(output_dir, os.path.basename(lib))
-
- if lib.startswith('/data/app'):
- # If this is our own library instead of a system one, look for a matching
- # unstripped library under the out directory.
- unstripped_host_lib = _FindMatchingUnstrippedLibraryOnHost(device, lib)
- if not unstripped_host_lib:
- logging.warning('Could not find symbols for %s.' % lib)
- logging.warning('Is the correct output directory selected '
- '(CHROMIUM_OUT_DIR)? Did you install the APK after '
- 'building?')
- continue
- if use_symlinks:
- if os.path.lexists(output_lib):
- os.remove(output_lib)
- os.symlink(os.path.abspath(unstripped_host_lib), output_lib)
- # Copy the unstripped library only if it has been changed to avoid the
- # delay.
- elif not _FileMetadataMatches(unstripped_host_lib, output_lib):
- logging.info('Copying %s to %s' % (unstripped_host_lib, output_lib))
- shutil.copy2(unstripped_host_lib, output_lib)
- else:
- # Otherwise save a copy of the stripped system library under the symfs so
- # the profiler can at least use the public symbols of that library. To
- # speed things up, only pull files that don't match copies we already
- # have in the symfs.
- if not os.path.exists(output_lib):
- pull = True
- else:
- host_md5sums = md5sum.CalculateHostMd5Sums([output_lib])
- try:
- device_md5sums = md5sum.CalculateDeviceMd5Sums([lib], device)
- except:
- logging.exception('New exception caused by DeviceUtils conversion')
- raise
-
- pull = True
- if host_md5sums and device_md5sums and output_lib in host_md5sums \
- and lib in device_md5sums:
- pull = host_md5sums[output_lib] != device_md5sums[lib]
-
- if pull:
- logging.info('Pulling %s to %s', lib, output_lib)
- device.PullFile(lib, output_lib)
-
- # Also pull a copy of the kernel symbols.
- output_kallsyms = os.path.join(symfs_dir, 'kallsyms')
- if not os.path.exists(output_kallsyms):
- device.PullFile('/proc/kallsyms', output_kallsyms)
- return output_kallsyms
-
-
-def PrepareDeviceForPerf(device):
- """Set up a device for running perf.
-
- Args:
- device: DeviceUtils instance identifying the target device.
-
- Returns:
- The path to the installed perf binary on the device.
- """
- android_prebuilt_profiler_helper.InstallOnDevice(device, 'perf')
- # Make sure kernel pointers are not hidden.
- device.WriteFile('/proc/sys/kernel/kptr_restrict', '0', as_root=True)
- return android_prebuilt_profiler_helper.GetDevicePath('perf')
-
-
-def GetToolchainBinaryPath(library_file, binary_name):
- """Return the path to an Android toolchain binary on the host.
-
- Args:
- library_file: ELF library which is used to identify the used ABI,
- architecture and toolchain.
- binary_name: Binary to search for, e.g., 'objdump'
- Returns:
- Full path to binary or None if the binary was not found.
- """
- # Mapping from ELF machine identifiers to GNU toolchain names.
- toolchain_configs = {
- 'x86': 'i686-linux-android',
- 'MIPS': 'mipsel-linux-android',
- 'ARM': 'arm-linux-androideabi',
- 'x86-64': 'x86_64-linux-android',
- 'AArch64': 'aarch64-linux-android',
- }
- toolchain_config = toolchain_configs[_ElfMachineId(library_file)]
- host_os = platform.uname()[0].lower()
- host_machine = platform.uname()[4]
-
- elf_comment = _ElfSectionAsString(library_file, '.comment')
- toolchain_version = re.match(r'.*GCC: \(GNU\) ([\w.]+)',
- elf_comment, re.DOTALL)
- if not toolchain_version:
- return None
- toolchain_version = toolchain_version.group(1)
-
- toolchain_path = os.path.abspath(os.path.join(
- util.GetChromiumSrcDir(), 'third_party', 'android_tools', 'ndk',
- 'toolchains', '%s-%s' % (toolchain_config, toolchain_version)))
- if not os.path.exists(toolchain_path):
- logging.warning(
- 'Unable to find toolchain binary %s: toolchain not found at %s',
- binary_name, toolchain_path)
- return None
-
- path = os.path.join(
- toolchain_path, 'prebuilt', '%s-%s' % (host_os, host_machine), 'bin',
- '%s-%s' % (toolchain_config, binary_name))
- if not os.path.exists(path):
- logging.warning(
- 'Unable to find toolchain binary %s: binary not found at %s',
- binary_name, path)
- return None
-
- return path

Powered by Google App Engine
This is Rietveld 408576698