def _StartCrashService(self): os_name = self.browser.platform.GetOSName() if os_name != 'win': return None arch_name = self.browser.platform.GetArchName() command = binary_manager.FetchPath('crash_service', arch_name, os_name) if not command: logging.warning('crash_service.exe not found for %s %s', arch_name, os_name) return None if not os.path.exists(command): logging.warning('crash_service.exe not found for %s %s', arch_name, os_name) return None try: crash_service = subprocess.Popen([ command, '--no-window', '--dumps-dir=%s' % self._tmp_minidump_dir, '--pipe-name=%s' % self._GetCrashServicePipeName() ]) except: logging.error( 'Failed to run %s --no-window --dump-dir=%s --pip-name=%s' % (command, self._tmp_minidump_dir, self._GetCrashServicePipeName())) logging.error('Running on platform: %s and arch: %s.', os_name, arch_name) raise return crash_service
def EnsureBackgroundApkInstalled(self): app = 'push_apps_to_background_apk' arch_name = self._device.GetABI() host_path = binary_manager.FetchPath(app, arch_name, 'android') if not host_path: raise Exception('Error installing PushAppsToBackground.apk.') self.InstallApplication(host_path)
def _StartCrashService(self): os_name = self.browser.platform.GetOSName() if os_name != 'win': return None arch_name = self.browser.platform.GetArchName() command = binary_manager.FetchPath('crash_service', arch_name, os_name) if not command: logging.warning('crash_service.exe not found for %s %s', arch_name, os_name) return None if not os.path.exists(command): logging.warning('crash_service.exe not found for %s %s', arch_name, os_name) return None try: crash_service = subprocess.Popen([ command, '--no-window', '--dumps-dir=%s' % self._tmp_minidump_dir, '--pipe-name=%s' % self._GetCrashServicePipeName()]) except Exception: logging.error( 'Failed to run %s --no-window --dump-dir=%s --pip-name=%s' % ( command, self._tmp_minidump_dir, self._GetCrashServicePipeName())) logging.error('Running on platform: %s and arch: %s.', os_name, arch_name) wmic_stdout, _ = subprocess.Popen( ['wmic', 'process', 'get', 'CommandLine,Name,ProcessId,ParentProcessId', '/format:csv'], stdout=subprocess.PIPE).communicate() logging.error('Current running processes:\n%s' % wmic_stdout) raise return crash_service
def _GetGoBinaryPath(cls): if not cls._go_binary_path: if binary_manager.NeedsInit(): binary_manager.InitDependencyManager(None) cls._go_binary_path = binary_manager.FetchPath( 'wpr_go', py_utils.GetHostArchName(), py_utils.GetHostOsName()) return cls._go_binary_path
def SymbolizeMinidump(self, minidump): """Gets the stack trace from the given minidump. Args: minidump: the path to the minidump on disk Returns: None if the stack could not be retrieved for some reason, otherwise a string containing the stack trace. """ stackwalk = binary_manager.FetchPath( 'minidump_stackwalk', self._arch_name, self._os_name) if not stackwalk: logging.warning('minidump_stackwalk binary not found.') return None # We only want this logic on linux platforms that are still using breakpad. # See crbug.com/667475 if not self._dump_finder.MinidumpObtainedFromCrashpad(minidump): with open(minidump, 'rb') as infile: minidump += '.stripped' with open(minidump, 'wb') as outfile: outfile.write(''.join(infile.read().partition('MDMP')[1:])) symbols_dir = tempfile.mkdtemp() try: self._GenerateBreakpadSymbols(symbols_dir, minidump) return subprocess.check_output([stackwalk, minidump, symbols_dir], stderr=open(os.devnull, 'w')) finally: shutil.rmtree(symbols_dir)
def GenerateBreakpadSymbols(arch, os_name, symbols_dir, build_dir): """Generates Breakpad symbols for the given build directory. Args: arch: the architecture of the host, used to find dependencies os_name: the OS of the host, used to find dependencies symbols_dir: the directory where Breakpad symbols will be dumped to build_dir: the directory containing Chromium build artifacts to generate symbols from. """ logging.info('Dumping breakpad symbols.') generate_breakpad_symbols_command = binary_manager.FetchPath( 'generate_breakpad_symbols', arch, os_name) if not generate_breakpad_symbols_command: logging.warning('generate_breakpad_symbols binary not found') return cmd = [ sys.executable, generate_breakpad_symbols_command, '--binary=%s' % os.path.join(build_dir, 'chrome'), '--symbols-dir=%s' % symbols_dir, '--build-dir=%s' % build_dir, '--platform=chromeos', ] try: subprocess.check_output(cmd) except subprocess.CalledProcessError as e: logging.error(e.output) logging.warning('Failed to execute "%s"', ' '.join(cmd)) return
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 _GenerateBreakpadSymbols(self, symbols_dir, minidump): """Generates Breakpad symbols for use with stackwalking tools. Args: symbols_dir: The directory where symbols will be written to. minidump: The path to the minidump being symbolized. """ logging.info('Dumping Breakpad symbols.') generate_breakpad_symbols_command = binary_manager.FetchPath( 'generate_breakpad_symbols', self._arch_name, self._os_name) if not generate_breakpad_symbols_command: logging.warning('generate_breakpad_symbols binary not found') return for binary_path in self.GetSymbolBinaries(minidump): cmd = [ sys.executable, generate_breakpad_symbols_command, '--binary=%s' % binary_path, '--symbols-dir=%s' % symbols_dir, '--build-dir=%s' % self._build_dir, ] if self.GetBreakpadPlatformOverride(): cmd.append('--platform=%s' % self.GetBreakpadPlatformOverride()) try: subprocess.check_output(cmd) except subprocess.CalledProcessError as e: logging.error(e.output) logging.warning('Failed to execute "%s"', ' '.join(cmd)) return
def _GetAllCrashpadMinidumps(self): os_name = self.browser.platform.GetOSName() arch_name = self.browser.platform.GetArchName() try: crashpad_database_util = binary_manager.FetchPath( 'crashpad_database_util', arch_name, os_name) if not crashpad_database_util: logging.warning('No crashpad_database_util found') return None except dependency_manager.NoPathFoundError: logging.warning('No path to crashpad_database_util found') return None logging.info('Found crashpad_database_util') report_output = subprocess.check_output([ crashpad_database_util, '--database=' + self._tmp_minidump_dir, '--show-pending-reports', '--show-completed-reports', '--show-all-report-info']) last_indentation = -1 reports_list = [] report_dict = {} for report_line in report_output.splitlines(): # Report values are grouped together by the same indentation level. current_indentation = 0 for report_char in report_line: if not report_char.isspace(): break current_indentation += 1 # Decrease in indentation level indicates a new report is being printed. if current_indentation >= last_indentation: report_key, report_value = report_line.split(':', 1) if report_value: report_dict[report_key.strip()] = report_value.strip() elif report_dict: try: report_time = ParseCrashpadDateTime(report_dict['Creation time']) report_path = report_dict['Path'].strip() reports_list.append((report_time, report_path)) except (ValueError, KeyError) as e: logging.warning('Crashpad report expected valid keys' ' "Path" and "Creation time": %s', e) finally: report_dict = {} last_indentation = current_indentation # Include the last report. if report_dict: try: report_time = ParseCrashpadDateTime(report_dict['Creation time']) report_path = report_dict['Path'].strip() reports_list.append((report_time, report_path)) except (ValueError, KeyError) as e: logging.warning('Crashpad report expected valid keys' ' "Path" and "Creation time": %s', e) return reports_list
def FlushSystemCacheForDirectory(self, directory): assert directory and os.path.exists(directory), \ 'Target directory %s must exist' % directory flush_command = binary_manager.FetchPath( 'clear_system_cache', self.GetOSName(), self.GetArchName()) assert flush_command, 'You must build clear_system_cache first' subprocess.check_call([flush_command, '--recurse', directory])
def testFetchPathInitialized(self, binary_manager_mock): expected = [mock.call.binary_manager.BinaryManager( ['base_config_object']), mock.call.binary_manager.BinaryManager().FetchPath( 'dep', 'plat_arch')] binary_manager.InitDependencyManager(None) binary_manager.FetchPath('dep', 'plat', 'arch') binary_manager_mock.assert_call_args(expected)
def _InstallHorndis(self, arch_name): if self._LoadInstalledHoRNDIS(): logging.info('HoRNDIS kext loaded successfully.') return logging.info('Installing HoRNDIS...') pkg_path = binary_manager.FetchPath('horndis', 'mac', arch_name) subprocess.check_call( ['/usr/bin/sudo', 'installer', '-pkg', pkg_path, '-target', '/'])
def _FindAllPossibleBrowsers(finder_options, android_platform): """Testable version of FindAllAvailableBrowsers.""" if not android_platform: return [] possible_browsers = [] # Add the exact APK if given. if _CanPossiblyHandlePath(finder_options.browser_executable): if not os.path.exists(finder_options.browser_executable): raise exceptions.PathMissingError( 'Unable to find exact apk specified by --browser-executable=%s' % finder_options.browser_executable) package_name = apk_helper.GetPackageName( finder_options.browser_executable) try: backend_settings = next(backend_settings for target_package, backend_settings in CHROME_PACKAGE_NAMES.itervalues() if package_name == target_package) except StopIteration: raise exceptions.UnknownPackageError( '%s specified by --browser-executable has an unknown package: %s' % (finder_options.browser_executable, package_name)) possible_browsers.append( PossibleAndroidBrowser('exact', finder_options, android_platform, backend_settings(package_name), finder_options.browser_executable)) # Add the reference build if found. os_version = dependency_util.GetChromeApkOsVersion( android_platform.GetOSVersionName()) arch = android_platform.GetArchName() try: reference_build = binary_manager.FetchPath('chrome_stable', arch, 'android', os_version) except (binary_manager.NoPathFoundError, binary_manager.CloudStorageError): reference_build = None if reference_build and os.path.exists(reference_build): # TODO(aiolos): how do we stably map the android chrome_stable apk to the # correct package name? package, backend_settings = CHROME_PACKAGE_NAMES['android-chrome'] possible_browsers.append( PossibleAndroidBrowser('reference', finder_options, android_platform, backend_settings(package), reference_build)) # Add any known local versions. for name, package_info in CHROME_PACKAGE_NAMES.iteritems(): package, backend_settings = package_info p_browser = PossibleAndroidBrowser(name, finder_options, android_platform, backend_settings(package)) if p_browser.IsAvailable(): possible_browsers.append(p_browser) return possible_browsers
def _GetMinidumpStackwalkPath(self): """Gets the path to the minidump_stackwalk binary to use.""" # TODO(https://crbug.com/1054583): Remove this once Telemetry searches # locally for all dependencies automatically. stackwalk_path = os.path.join(self._build_dir, 'minidump_stackwalk') if not os.path.exists(stackwalk_path): stackwalk_path = binary_manager.FetchPath( 'minidump_stackwalk', self._arch_name, self._os_name) return stackwalk_path
def FetchExampleDomainArchive(): ''' Return the path to wpr go archive of example.com page. This may involve fetching the archives from cloud storage if it doesn't exist on local file system. ''' p = platform.GetHostPlatform() return binary_manager.FetchPath('example_domain_wpr_go_archive', p.GetArchName(), p.GetOSName())
def _FindAllPossibleBrowsers(finder_options, android_platform): """Testable version of FindAllAvailableBrowsers.""" if not android_platform: return [] possible_browsers = [] # Add the exact APK if given. if _CanPossiblyHandlePath(finder_options.browser_executable): if not os.path.exists(finder_options.browser_executable): raise exceptions.PathMissingError( 'Unable to find exact apk specified by --browser-executable=%s' % finder_options.browser_executable) package_name = apk_helper.GetPackageName( finder_options.browser_executable) try: backend_settings = next(b for b in ANDROID_BACKEND_SETTINGS if b.package == package_name) except StopIteration: raise exceptions.UnknownPackageError( '%s specified by --browser-executable has an unknown package: %s' % (finder_options.browser_executable, package_name)) possible_browsers.append( PossibleAndroidBrowser('exact', finder_options, android_platform, backend_settings, finder_options.browser_executable)) # Add the reference build if found. os_version = dependency_util.GetChromeApkOsVersion( android_platform.GetOSVersionName()) arch = android_platform.GetArchName() try: reference_build = binary_manager.FetchPath('chrome_stable', arch, 'android', os_version) except (binary_manager.NoPathFoundError, binary_manager.CloudStorageError): reference_build = None if reference_build and os.path.exists(reference_build): # TODO(aiolos): how do we stably map the android chrome_stable apk to the # correct backend settings? possible_browsers.append( PossibleAndroidBrowser( 'reference', finder_options, android_platform, android_browser_backend_settings.ANDROID_CHROME, reference_build)) # Add any other known available browsers. for settings in ANDROID_BACKEND_SETTINGS: p_browser = PossibleAndroidBrowser(settings.browser_type, finder_options, android_platform, settings) if p_browser.IsAvailable(): possible_browsers.append(p_browser) return possible_browsers
def testFetchPathInitialized(self, base_config_mock, dep_manager_mock): base_config_mock.return_value = 'base_config_object' expected = [mock.call.dependency_manager.DependencyManager( ['base_config_object']), mock.call.dependency_manager.DependencyManager().FetchPath( 'dep', 'plat_arch')] binary_manager.InitDependencyManager(None) binary_manager.FetchPath('dep', 'plat', 'arch') dep_manager_mock.assert_call_args(expected) base_config_mock.assert_called_once_with( binary_manager.TELEMETRY_PROJECT_CONFIG)
def InstallOnDevice(device, profiler_binary): arch_name = device.GetABI() host_path = binary_manager.FetchPath(profiler_binary, arch_name, 'android') if not host_path: logging.error('Profiler binary "%s" not found. Could not be installed', host_path) return False device_binary_path = GetDevicePath(profiler_binary) device.PushChangedFiles([(host_path, device_binary_path)]) device.RunShellCommand('chmod 777 ' + device_binary_path) return True
def GetSymbolBinaries(self, minidump): """Returns a list of paths to binaries where symbols may be located. Args: minidump: The path to the minidump being symbolized. """ # TODO(https://crbug.com/1054583): Remove this once Telemetry searches # locally for all dependencies automatically. minidump_dump = os.path.join(self._build_dir, 'minidump_dump') if not os.path.exists(minidump_dump): logging.warning( 'Unable to find locally built minidump_dump, using Catapult version.' ) minidump_dump = binary_manager.FetchPath('minidump_dump', self._os_name, self._arch_name) assert minidump_dump symbol_binaries = [] minidump_cmd = [minidump_dump, minidump] try: with open(os.devnull, 'wb') as dev_null: minidump_output = subprocess.check_output(minidump_cmd, stderr=dev_null) except subprocess.CalledProcessError as e: # For some reason minidump_dump always fails despite successful dumping. minidump_output = e.output minidump_binary_re = re.compile(r'\W+\(code_file\)\W+=\W\"(.*)\"') for minidump_line in minidump_output.splitlines(): line_match = minidump_binary_re.match(minidump_line) if line_match: binary_path = line_match.group(1) if not os.path.isfile(binary_path): continue # Filter out system binaries. if (binary_path.startswith('/usr/lib/') or binary_path.startswith('/System/Library/') or binary_path.startswith('/lib/')): continue # Filter out other binary file types which have no symbols. if (binary_path.endswith('.pak') or binary_path.endswith('.bin') or binary_path.endswith('.dat') or binary_path.endswith('.ttf')): continue symbol_binaries.append(binary_path) return self._FilterSymbolBinaries(symbol_binaries)
def _PushFilesAndStartService(self, arch_name): perfetto_device_path = posixpath.join(ANDROID_TMP_DIR, PERFETTO) traced_device_path = posixpath.join(ANDROID_TMP_DIR, TRACED) traced_probes_device_path = posixpath.join(ANDROID_TMP_DIR, TRACED_PROBES) perfetto_local_path = binary_manager.FetchPath( 'perfetto_monolithic_perfetto', 'android', arch_name) traced_local_path = binary_manager.FetchPath( 'perfetto_monolithic_traced', 'android', arch_name) traced_probes_local_path = binary_manager.FetchPath( 'perfetto_monolithic_traced_probes', 'android', arch_name) self._device.PushChangedFiles([ (perfetto_local_path, perfetto_device_path), (traced_local_path, traced_device_path), (traced_probes_local_path, traced_probes_device_path), ]) in_background = '</dev/null >/dev/null 2>&1 &' self._device.RunShellCommand(traced_device_path + in_background, shell=True) self._device.RunShellCommand(traced_probes_device_path + in_background, shell=True) self._perfetto_path = perfetto_device_path
def _GetReferenceAndroidBrowser(android_platform, finder_options): # Add the reference build if found. os_version = dependency_util.GetChromeApkOsVersion( android_platform.GetOSVersionName()) arch = android_platform.GetArchName() try: reference_build = binary_manager.FetchPath('chrome_stable', arch, 'android', os_version) except (binary_manager.NoPathFoundError, binary_manager.CloudStorageError): reference_build = None if reference_build and os.path.exists(reference_build): return PossibleAndroidBrowser( 'reference', finder_options, android_platform, android_browser_backend_settings.ANDROID_CHROME, reference_build)
def _GetStackFromMinidump(self, minidump): os_name = self.browser.platform.GetOSName() if os_name == 'win': cdb = self._GetCdbPath() if not cdb: logging.warning('cdb.exe not found.') return None # Move to the thread which triggered the exception (".ecxr"). Then include # a description of the exception (".lastevent"). Also include all the # threads' stacks ("~*kb30") as well as the ostensibly crashed stack # associated with the exception context record ("kb30"). Note that stack # dumps, including that for the crashed thread, may not be as precise as # the one starting from the exception context record. # Specify kb instead of k in order to get four arguments listed, for # easier diagnosis from stacks. output = subprocess.check_output([ cdb, '-y', self._browser_directory, '-c', '.ecxr;.lastevent;kb30;~*kb30;q', '-z', minidump ]) # The output we care about starts with "Last event:" or possibly # other things we haven't seen yet. If we can't find the start of the # last event entry, include output from the beginning. info_start = 0 info_start_match = re.search("Last event:", output, re.MULTILINE) if info_start_match: info_start = info_start_match.start() info_end = output.find('quit:') return output[info_start:info_end] arch_name = self.browser.platform.GetArchName() stackwalk = binary_manager.FetchPath('minidump_stackwalk', arch_name, os_name) if not stackwalk: logging.warning('minidump_stackwalk binary not found.') return None # We only want this logic on linux platforms that are still using breakpad. # See crbug.com/667475 if not self._MinidumpObtainedFromCrashpad(minidump): with open(minidump, 'rb') as infile: minidump += '.stripped' with open(minidump, 'wb') as outfile: outfile.write(''.join(infile.read().partition('MDMP')[1:])) symbols_path = os.path.join(self._tmp_minidump_dir, 'symbols') GenerateBreakpadSymbols(minidump, arch_name, os_name, symbols_path, self._browser_directory) return subprocess.check_output([stackwalk, minidump, symbols_path], stderr=open(os.devnull, 'w'))
def _StartCrashService(self): os_name = self.browser.platform.GetOSName() if os_name != 'win': return None arch_name = self.browser.platform.GetArchName() command = binary_manager.FetchPath('crash_service', arch_name, os_name) if not command: logging.warning('crash_service.exe not found for %s %s', arch_name, os_name) return None return subprocess.Popen([ command, '--no-window', '--dumps-dir=%s' % self._tmp_minidump_dir, '--pipe-name=%s' % self._GetCrashServicePipeName() ])
def PullTrace(self): symfs_dir = os.path.join(tempfile.gettempdir(), os.path.expandvars('$USER-perf-symfs')) if not os.path.exists(symfs_dir): os.makedirs(symfs_dir) required_libs = set() # Download the recorded perf profile. perf_profile = self._perf_instance.PullResult(symfs_dir) required_libs = \ android_profiling_helper.GetRequiredLibrariesForPerfProfile( perf_profile) if not required_libs: logging.warning( 'No libraries required by perf trace. Most likely there ' 'are no samples in the trace.') # Build a symfs with all the necessary libraries. kallsyms = android_profiling_helper.CreateSymFs(self._device, symfs_dir, required_libs, use_symlinks=False) perfhost_path = binary_manager.FetchPath( android_profiling_helper.GetPerfhostName(), 'x86_64', 'linux') ui.PrintMessage('\nNote: to view the profile in perf, run:') ui.PrintMessage(' ' + self._GetInteractivePerfCommand( perfhost_path, perf_profile, symfs_dir, required_libs, kallsyms)) # Convert the perf profile into JSON. perf_script_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'third_party', 'perf_to_tracing.py') json_file_name = os.path.basename(perf_profile) with open(os.devnull, 'w') as dev_null, \ open(json_file_name, 'w') as json_file: cmd = [ perfhost_path, 'script', '-s', perf_script_path, '-i', perf_profile, '--symfs', symfs_dir, '--kallsyms', kallsyms ] if subprocess.call(cmd, stdout=json_file, stderr=dev_null): logging.warning( 'Perf data to JSON conversion failed. The result will ' 'not contain any perf samples. You can still view the ' 'perf data manually as shown above.') return None return json_file_name
def _InstallSimpleperf(self): if self._device_simpleperf_path is None: device = self._browser._platform_backend.device package = self._browser._browser_backend.package # This is the architecture of the app to be profiled, not of the device. package_arch = device.GetPackageArchitecture( package) or 'armeabi-v7a' host_path = binary_manager.FetchPath('simpleperf', package_arch, 'android') if not host_path: raise Exception( 'Could not get path to simpleperf executable on host.') device_path = os.path.join(self.DEVICE_PROFILERS_DIR, package_arch, 'simpleperf') device.PushChangedFiles([(host_path, device_path)]) self._device_simpleperf_path = device_path
def _InstallBinary(self, bin_name, fallback_package=None): bin_path = binary_manager.FetchPath(bin_name, self.GetArchName(), self.GetOSName()) if not bin_path: raise Exception('Could not find the binary package %s' % bin_name) os.environ['PATH'] += os.pathsep + os.path.dirname(bin_path) try: cloud_storage.GetIfChanged(bin_path, cloud_storage.INTERNAL_BUCKET) os.chmod(bin_path, 0755) except cloud_storage.CloudStorageError, e: logging.error(str(e)) if fallback_package: raise Exception( 'You may proceed by manually installing %s via:\n' 'sudo apt-get install %s' % (bin_name, fallback_package))
def _GetStackFromMinidump(self, minidump): os_name = self.browser.platform.GetOSName() if os_name == 'win': cdb = self._GetCdbPath() if not cdb: logging.warning('cdb.exe not found.') return None # Include all the threads' stacks ("~*kb30") in addition to the # ostensibly crashed stack associated with the exception context # record (".ecxr;kb30"). Note that stack dumps, including that # for the crashed thread, may not be as precise as the one # starting from the exception context record. # Specify kb instead of k in order to get four arguments listed, for # easier diagnosis from stacks. output = subprocess.check_output([ cdb, '-y', self._browser_directory, '-c', '.ecxr;kb30;~*kb30;q', '-z', minidump ]) # cdb output can start the stack with "ChildEBP", "Child-SP", and possibly # other things we haven't seen yet. If we can't find the start of the # stack, include output from the beginning. stack_start = 0 stack_start_match = re.search("^Child(?:EBP|-SP)", output, re.MULTILINE) if stack_start_match: stack_start = stack_start_match.start() stack_end = output.find('quit:') return output[stack_start:stack_end] arch_name = self.browser.platform.GetArchName() stackwalk = binary_manager.FetchPath('minidump_stackwalk', arch_name, os_name) if not stackwalk: logging.warning('minidump_stackwalk binary not found.') return None with open(minidump, 'rb') as infile: minidump += '.stripped' with open(minidump, 'wb') as outfile: outfile.write(''.join(infile.read().partition('MDMP')[1:])) symbols_path = os.path.join(self._tmp_minidump_dir, 'symbols') GenerateBreakpadSymbols(minidump, arch_name, os_name, symbols_path, self._browser_directory) return subprocess.check_output([stackwalk, minidump, symbols_path], stderr=open(os.devnull, 'w'))
def testFetchPathInitialized(self, base_config_mock, binary_manager_mock): base_config_mock.return_value = 'base_config_object' expected = [ mock.call.binary_manager.BinaryManager(['base_config_object']), mock.call.binary_manager.BinaryManager().FetchPath( 'dep', 'plat_arch') ] binary_manager.InitDependencyManager(None) binary_manager.FetchPath('dep', 'plat', 'arch') binary_manager_mock.assert_call_args(expected) base_config_mock.assert_has_calls([ mock.call.base_config.BaseConfig( binary_manager.TELEMETRY_PROJECT_CONFIG), mock.call.base_config.BaseConfig( binary_manager.CHROME_BINARY_CONFIG) ]) self.assertEqual(2, base_config_mock.call_count)
def GetSymbolBinaries(self, minidump): """Returns a list of paths to binaries where symbols may be located. Args: minidump: The path to the minidump being symbolized. """ minidump_dump = binary_manager.FetchPath('minidump_dump', self._arch_name, self._os_name) assert minidump_dump symbol_binaries = [] minidump_cmd = [minidump_dump, minidump] try: with open(os.devnull, 'wb') as dev_null: minidump_output = subprocess.check_output(minidump_cmd, stderr=dev_null) except subprocess.CalledProcessError as e: # For some reason minidump_dump always fails despite successful dumping. minidump_output = e.output minidump_binary_re = re.compile(r'\W+\(code_file\)\W+=\W\"(.*)\"') for minidump_line in minidump_output.splitlines(): line_match = minidump_binary_re.match(minidump_line) if line_match: binary_path = line_match.group(1) if not os.path.isfile(binary_path): continue # Filter out system binaries. if (binary_path.startswith('/usr/lib/') or binary_path.startswith('/System/Library/') or binary_path.startswith('/lib/')): continue # Filter out other binary file types which have no symbols. if (binary_path.endswith('.pak') or binary_path.endswith('.bin') or binary_path.endswith('.dat') or binary_path.endswith('.ttf')): continue symbol_binaries.append(binary_path) return symbol_binaries
def _InstallSimpleperf(cls, possible_browser): device = possible_browser._platform_backend.device package = possible_browser._backend_settings.package # Necessary for profiling # https://android-review.googlesource.com/c/platform/system/sepolicy/+/234400 device.SetProp('security.perf_harden', '0') # This is the architecture of the app to be profiled, not of the device. package_arch = device.GetPackageArchitecture(package) or 'armeabi-v7a' host_path = binary_manager.FetchPath('simpleperf', package_arch, 'android') if not host_path: raise Exception( 'Could not get path to simpleperf executable on host.') device_path = os.path.join(cls.DEVICE_PROFILERS_DIR, package_arch, 'simpleperf') device.PushChangedFiles([(host_path, device_path)]) return device_path