Esempio n. 1
0
    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)
Esempio n. 3
0
  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
Esempio n. 4
0
 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
Esempio n. 5
0
  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)
Esempio n. 6
0
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
Esempio n. 8
0
    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
Esempio n. 10
0
  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)
Esempio n. 12
0
 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', '/'])
Esempio n. 13
0
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
Esempio n. 14
0
 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
Esempio n. 15
0
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())
Esempio n. 16
0
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)
Esempio n. 18
0
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
Esempio n. 19
0
    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)
Esempio n. 20
0
 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)
Esempio n. 22
0
    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'))
Esempio n. 23
0
 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()
     ])
Esempio n. 24
0
    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
Esempio n. 25
0
 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
Esempio n. 26
0
    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)
Esempio n. 29
0
    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
Esempio n. 30
0
    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