android_profiling_helper.py revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved. 2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# found in the LICENSE file. 4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import glob 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import hashlib 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import logging 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import os 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import platform 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import re 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import shutil 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import subprocess 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifrom telemetry import decorators 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifrom telemetry.core import platform as telemetry_platform 166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)from telemetry.core import util 176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)from telemetry.core.platform.profiler import android_prebuilt_profiler_helper 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)from telemetry.util import support_binaries 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)try: 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) import sqlite3 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)except ImportError: 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sqlite3 = None 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)_TEXT_SECTION = '.text' 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def _ElfMachineId(elf_file): 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) headers = subprocess.check_output(['readelf', '-h', elf_file]) 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return re.match(r'.*Machine:\s+(\w+)', headers, re.DOTALL).group(1) 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def _ElfSectionAsString(elf_file, section): 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return subprocess.check_output(['readelf', '-p', section, elf_file]) 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def _ElfSectionMd5Sum(elf_file, section): 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) result = subprocess.check_output( 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'readelf -p%s "%s" | md5sum' % (section, elf_file), shell=True) 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return result.split(' ', 1)[0] 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def _FindMatchingUnstrippedLibraryOnHost(device, lib): 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) lib_base = os.path.basename(lib) 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device_md5 = device.RunShellCommand('md5 "%s"' % lib, as_root=True)[0] 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) device_md5 = device_md5.split(' ', 1)[0] 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) def FindMatchingStrippedLibrary(out_path): 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) # First find a matching stripped library on the host. This avoids the need 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) # to pull the stripped library from the device, which can take tens of 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) # seconds. 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) host_lib_pattern = os.path.join(out_path, '*_apk', 'libs', '*', lib_base) 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for stripped_host_lib in glob.glob(host_lib_pattern): 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) with open(stripped_host_lib) as f: 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) host_md5 = hashlib.md5(f.read()).hexdigest() 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if host_md5 == device_md5: 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return stripped_host_lib 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for build_dir, build_type in util.GetBuildDirectories(): 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) out_path = os.path.join(build_dir, build_type) 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stripped_host_lib = FindMatchingStrippedLibrary(out_path) 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if stripped_host_lib: 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else: 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return None 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # The corresponding unstripped library will be under out/Release/lib. 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unstripped_host_lib = os.path.join(out_path, 'lib', lib_base) 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Make sure the unstripped library matches the stripped one. We do this 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # by comparing the hashes of text sections in both libraries. This isn't an 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # exact guarantee, but should still give reasonable confidence that the 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # libraries are compatible. 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # TODO(skyostil): Check .note.gnu.build-id instead once we're using 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # --build-id=sha1. 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # pylint: disable=W0631 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (_ElfSectionMd5Sum(unstripped_host_lib, _TEXT_SECTION) != 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) _ElfSectionMd5Sum(stripped_host_lib, _TEXT_SECTION)): 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return None 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return unstripped_host_lib 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci@decorators.Cache 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef GetPerfhostName(): 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return 'perfhost_' + telemetry_platform.GetHostPlatform().GetOSVersionName() 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Ignored directories for libraries that aren't useful for symbolization. 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)_IGNORED_LIB_PATHS = [ 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '/data/dalvik-cache', 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '/tmp' 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)] 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def GetRequiredLibrariesForPerfProfile(profile_file): 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Returns the set of libraries necessary to symbolize a given perf profile. 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile_file: Path to perf profile to analyse. 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Returns: 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) A set of required library file names. 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) with open(os.devnull, 'w') as dev_null: 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci perfhost_path = support_binaries.FindPath(GetPerfhostName(), 'linux') 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) perf = subprocess.Popen([perfhost_path, 'script', '-i', profile_file], 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) stdout=dev_null, stderr=subprocess.PIPE) 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) _, output = perf.communicate() 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) missing_lib_re = re.compile( 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) r'^Failed to open (.*), continuing without symbols') 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) libs = set() 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for line in output.split('\n'): 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) lib = missing_lib_re.match(line) 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if lib: 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) lib = lib.group(1) 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) path = os.path.dirname(lib) 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if any(path.startswith(ignored_path) 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for ignored_path in _IGNORED_LIB_PATHS) or path == '/': 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) libs.add(lib) 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return libs 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def GetRequiredLibrariesForVTuneProfile(profile_file): 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) """Returns the set of libraries necessary to symbolize a given VTune profile. 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Args: 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) profile_file: Path to VTune profile to analyse. 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Returns: 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) A set of required library file names. 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) """ 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) db_file = os.path.join(profile_file, 'sqlite-db', 'dicer.db') 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) conn = sqlite3.connect(db_file) 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) try: 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) # The 'dd_module_file' table lists all libraries on the device. Only the 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) # ones with 'bin_located_path' are needed for the profile. 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) query = 'SELECT bin_path, bin_located_path FROM dd_module_file' 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return set(row[0] for row in conn.cursor().execute(query) if row[1]) 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) finally: 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) conn.close() 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def CreateSymFs(device, symfs_dir, libraries, use_symlinks=True): 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Creates a symfs directory to be used for symbolizing profiles. 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Prepares a set of files ("symfs") to be used with profilers such as perf for 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) converting binary addresses into human readable function names. 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) device: DeviceUtils instance identifying the target device. 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) symfs_dir: Path where the symfs should be created. 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) libraries: Set of library file names that should be included in the symfs. 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) use_symlinks: If True, link instead of copy unstripped libraries into the 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) symfs. This will speed up the operation, but the resulting symfs will no 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) longer be valid if the linked files are modified, e.g., by rebuilding. 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Returns: 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) The absolute path to the kernel symbols within the created symfs. 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info('Building symfs into %s.' % symfs_dir) 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mismatching_files = {} 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for lib in libraries: 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) device_dir = os.path.dirname(lib) 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) output_dir = os.path.join(symfs_dir, device_dir[1:]) 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not os.path.exists(output_dir): 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) os.makedirs(output_dir) 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) output_lib = os.path.join(output_dir, os.path.basename(lib)) 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if lib.startswith('/data/app/'): 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # If this is our own library instead of a system one, look for a matching 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # unstripped library under the out directory. 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unstripped_host_lib = _FindMatchingUnstrippedLibraryOnHost(device, lib) 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not unstripped_host_lib: 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.warning('Could not find symbols for %s.' % lib) 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.warning('Is the correct output directory selected ' 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '(CHROMIUM_OUT_DIR)? Did you install the APK after ' 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'building?') 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if use_symlinks: 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if os.path.lexists(output_lib): 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) os.remove(output_lib) 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) os.symlink(os.path.abspath(unstripped_host_lib), output_lib) 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Copy the unstripped library only if it has been changed to avoid the 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # delay. Add one second to the modification time to guard against file 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # systems with poor timestamp resolution. 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) elif not os.path.exists(output_lib) or \ 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (os.stat(unstripped_host_lib).st_mtime > 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) os.stat(output_lib).st_mtime + 1): 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info('Copying %s to %s' % (unstripped_host_lib, output_lib)) 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) shutil.copy2(unstripped_host_lib, output_lib) 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else: 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Otherwise save a copy of the stripped system library under the symfs so 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # the profiler can at least use the public symbols of that library. To 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # speed things up, only pull files that don't match copies we already 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # have in the symfs. 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not device_dir in mismatching_files: 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) changed_files = device.old_interface.GetFilesChanged(output_dir, 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) device_dir) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) mismatching_files[device_dir] = [ 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) device_path for _, device_path in changed_files] 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not os.path.exists(output_lib) or lib in mismatching_files[device_dir]: 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info('Pulling %s to %s' % (lib, output_lib)) 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device.PullFile(lib, output_lib) 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Also pull a copy of the kernel symbols. 213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) output_kallsyms = os.path.join(symfs_dir, 'kallsyms') 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not os.path.exists(output_kallsyms): 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device.PullFile('/proc/kallsyms', output_kallsyms) 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return output_kallsyms 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def PrepareDeviceForPerf(device): 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Set up a device for running perf. 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) device: DeviceUtils instance identifying the target device. 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Returns: 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) The path to the installed perf binary on the device. 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) android_prebuilt_profiler_helper.InstallOnDevice(device, 'perf') 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Make sure kernel pointers are not hidden. 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device.WriteFile('/proc/sys/kernel/kptr_restrict', '0', as_root=True) 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return android_prebuilt_profiler_helper.GetDevicePath('perf') 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def GetToolchainBinaryPath(library_file, binary_name): 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) """Return the path to an Android toolchain binary on the host. 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Args: 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) library_file: ELF library which is used to identify the used ABI, 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) architecture and toolchain. 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) binary_name: Binary to search for, e.g., 'objdump' 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Returns: 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Full path to binary or None if the binary was not found. 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) """ 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) # Mapping from ELF machine identifiers to GNU toolchain names. 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) toolchain_configs = { 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'x86': 'i686-linux-android', 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'MIPS': 'mipsel-linux-android', 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'ARM': 'arm-linux-androideabi', 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'x86-64': 'x86_64-linux-android', 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'AArch64': 'aarch64-linux-android', 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) toolchain_config = toolchain_configs[_ElfMachineId(library_file)] 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) host_os = platform.uname()[0].lower() 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) host_machine = platform.uname()[4] 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) elf_comment = _ElfSectionAsString(library_file, '.comment') 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) toolchain_version = re.match(r'.*GCC: \(GNU\) ([\w.]+)', 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) elf_comment, re.DOTALL) 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if not toolchain_version: 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return None 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) toolchain_version = toolchain_version.group(1) 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) path = os.path.join(util.GetChromiumSrcDir(), 'third_party', 'android_tools', 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'ndk', 'toolchains', 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '%s-%s' % (toolchain_config, toolchain_version), 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'prebuilt', '%s-%s' % (host_os, host_machine), 'bin', 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '%s-%s' % (toolchain_config, binary_name)) 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) path = os.path.abspath(path) 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return path if os.path.exists(path) else None 270