如何调试 chrome 崩溃日志(MAC)

embedded/2024/11/26 5:02:43/

引言

在使用 Chrome 浏览器的过程中,偶尔会遇到浏览器崩溃的情况。为了找出崩溃的原因并修复问题,我们需要对崩溃后的 .dmp 文件进行详细分析。本文将详细介绍如何从用户的系统中获取崩溃日志文件,使用 minidump_stackwalk 查看浏览器版本信息,下载对应的 symbols 文件,并使用 LLDB 进行详细分析。

第一步:获取崩溃日志文件

1.1 收集 .dmp 文件
当 Chrome 浏览器崩溃时,系统通常会生成一个 .dmp 文件,该文件包含了崩溃时的堆栈信息。用户可以在 Chrome 的崩溃报告目录中找到这些文件。路径通常为:

  • Windows: C:\Users<Username>\AppData\Local\Google\Chrome\User Data\Crash Reports
  • macOS: ~/Library/Application Support/Google/Chrome/Crash Reports
  • Linux: ~/.config/google-chrome/Crash Reports

第二步:使用 minidump_stackwalk 查看浏览器版本信息

2.1 安装 minidump_stackwalk

确保你的系统上安装了 minidump_stackwalk。你可以通过以下命令安装:

# macOS 和 Linux
brew install breakpad

或者从源码编译安装:

git clone https://chromium.googlesource.com/breakpad/breakpad
cd breakpad
./configure
make
sudo make install

2.2 使用 minidump_stackwalk 查看信息

使用 minidump_stackwalk 工具查看 .dmp 文件中的浏览器版本信息:

minidump_stackwalk your_crash.dmp /path/to/symbols

该命令会输出崩溃的详细信息,包括浏览器版本、模块列表等。根据输出的版本信息,

第三步:下载 symbols 文件

3.1 访问 Chrome 官方网站

根据 minidump_stackwalk 输出的版本信息,访问 Chrome 官方下载页面 下载对应的 symbols 文件。通常,symbols 文件可以在 Chrome 的开发者资源页面找到。
github 上有一个辅助下载脚本(download_symbols.py),有些处理过时了,略作修改如下所示:

#!/usr/bin/env python3
# Copyright 2021 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.
"""Downloads symbols for official, Google Chrome builds.Usage:./download_symbols.py -v 91.0.4449.6 -a x86_64 -c stable -o /dest/pathThis can also be used as a Python module.
"""import argparse
import csv
import os.path
import platform
import subprocess
import sys
import urllib.request as request# 这个地址已经失效了,channel 需要手动指定(比如 【stable】,可以在 https://chromiumdash.appspot.com/releases?platform=Mac 中查看)
_OMAHAPROXY_HISTORY = 'https://omahaproxy.appspot.com/history?os=mac&format=json'_DSYM_URL_TEMPLATE = 'https://dl.google.com/chrome/mac/{channel}/dsym/googlechrome-{version}-{arch}-dsym.tar.bz2'def download_chrome_symbols(version, channel, arch, dest_dir):"""Downloads and extracts the official Google Chrome dSYM files to asubdirectory of `dest_dir`.Args:version: The version to download symbols for.channel: The release channel to download symbols for. If None, attemptsto guess the channel.arch: The CPU architecture to download symbols for.dest_dir: The location to download symbols to. The dSYMs will beextracted to a subdirectory of this directory.Returns:The path to the directory containing the dSYMs, which will be asubdirectory of `dest_dir`."""if channel is None:channel = _identify_channel(version, arch)if channel:print('Using release channel {} for {}'.format(channel, version),file=sys.stderr)else:print('Could not identify channel for Chrome version {}'.format(version),file=sys.stderr)return Noneextracted_dir = _download_and_extract(version, channel, arch, dest_dir)if not extracted_dir:print('Could not find dSYMs for Chrome {} {}'.format(version, arch),file=sys.stderr)return extracted_dirdef get_symbol_directory(version, channel, arch, dest_dir):"""Returns the parent directory for dSYMs given the specified parameters."""_, dest = _get_url_and_dest(version, channel, arch, dest_dir)return destdef _identify_channel(version, arch):"""Attempts to guess the release channel given a Chrome version and CPUarchitecture."""# First try querying OmahaProxy for the release.with request.urlopen(_OMAHAPROXY_HISTORY) as release_history:history = csv.DictReader(release_history.read().decode('utf8').split('\n'))for row in history:if row['version'] == version:return row['channel']# Fall back to sending HEAD HTTP requests to each of the possible symbol# locations.print('Unable to identify release channel for {}, now brute-force searching'.format(version),file=sys.stderr)for channel in ('stable', 'beta', 'dev', 'canary'):url, _ = _get_url_and_dest(version, channel, arch, '')req = request.Request(url, method='HEAD')try:resp = request.urlopen(req)if resp.code == 200:return channelexcept:continuereturn Nonedef _get_url_and_dest(version, channel, arch, dest_dir):"""Returns a the symbol archive URL and local destination directory giventhe format parameters."""args = {'channel': channel, 'arch': arch, 'version': version}url = _DSYM_URL_TEMPLATE.format(**args)dest_dir = os.path.join(dest_dir,'googlechrome-{version}-{arch}-dsym'.format(**args))return url, dest_dirdef _download_and_extract(version, channel, arch, dest_dir):"""Performs the download and extraction of the symbol files. Returns thepath to the extracted symbol files on success, None on error."""url, dest_dir = _get_url_and_dest(version, channel, arch, dest_dir)if not os.path.isdir(dest_dir):os.mkdir(dest_dir)print('download from {}'.format(url), file=sys.stderr)print(url, file=sys.stderr)try:with request.urlopen(url) as symbol_request:print('Downloading and extracting symbols to {}'.format(dest_dir),file=sys.stderr)print('This will take a minute...', file=sys.stderr)if _extract_symbols_to(symbol_request, dest_dir):return dest_direxcept:print('load failed!!!', file=sys.stderr)passreturn Nonedef _extract_symbols_to(symbol_request, dest_dir):"""Performs a streaming extract of the symbol files.Args:symbol_request: The HTTPResponse object for the symbol URL.dest_dir: The destination directory into which the files will beextracted.Returns: True on successful download and extraction, False on error."""proc = subprocess.Popen(['tar', 'xjf', '-'],cwd=dest_dir,stdin=subprocess.PIPE,stdout=sys.stderr,stderr=sys.stderr)while True:data = symbol_request.read(4096)if not data:proc.stdin.close()breakproc.stdin.write(data)proc.wait()return proc.returncode == 0def main():parser = argparse.ArgumentParser()parser.add_argument('--version','-v',required=True,help='Version to download.')parser.add_argument('--channel','-c',help='Chrome release channel for the version. The channel will be ' \'guessed if not specified.')parser.add_argument('--arch','-a',help='CPU architecture to download, defaults to that of the current OS.')parser.add_argument('--out','-o',required=True,help='Directory to download the symbols to.')args = parser.parse_args()arch = args.archif not arch:arch = platform.machine()if not os.path.isdir(args.out):print('--out destination is not a directory.', file=sys.stderr)return Falsereturn download_chrome_symbols(args.version, args.channel, arch, args.out)if __name__ == '__main__':main()

3.2 放置 symbols 文件

将下载的 symbols 文件放置在你指定的目录,例如 /path/to/symbols。

第四步:使用 LLDB 进行详细分析

4.1 安装 LLDB

确保你的系统上安装了 LLDB。大多数现代 macOS 和 Linux 发行版都自带了 LLDB,Windows 用户可以通过 Visual Studio 安装。

4.2 使用 LLDB 分析 .dmp 文件

打开终端,使用以下命令加载 .dmp 文件并进行分析:

lldb
(lldb) settings set target.exec-search-paths /symbol/file/path
(lldb) target create --core "/dmp/file/path"
(lldb) thread backtrace all

确保将 /path/to/executables 替换为你的 symbols 文件路径。

4.3 查看堆栈跟踪

使用以下命令查看崩溃时的堆栈跟踪:

(lldb) bt
这将显示详细的堆栈跟踪信息,帮助你定位崩溃的具体位置。之前定位过一个问题如下图所示:
<a class=crash信息截图" />
可以看出发生了 OOM,内存占用过大导致崩溃。

4.4 进一步调试

根据堆栈跟踪信息,你可以进一步调试,例如:

  • 检查变量值
  • 打印内存内容
  • 断点调试
(lldb) frame variable
(lldb) memory read --size 16 --format x --count 10 <address>

结论

这一过程有助于深入理解崩溃的原因,并采取相应的修复措施。希望本文能帮助你有效地分析 Chrome 浏览器的崩溃问题。如果你有任何疑问,欢迎一起探讨。
圣诞快乐,原图:https://lilysunshine.cn/wp-content/uploads/2024/11/christmas-glass-flow-vase.png.webp


http://www.ppmy.cn/embedded/140543.html

相关文章

金融服务的未来:测试自动化如何驱动合规、安全与创新

在快节奏、监管严格的金融服务领域&#xff0c;提供卓越的服务不仅仅关乎速度&#xff0c;还关乎管理巨大的复杂性。随着金融机构面临越来越大的创新压力&#xff0c;它们还肩负着维持严格的安全和合规标准的重任。 测试自动化不仅仅是一种工具&#xff1b;它 使团队能够 满怀…

HBase 原理

一、HBase系统架构 HBase采用主从架构&#xff0c;主要由以下几个组件组成&#xff1a; Client&#xff1a;客户端&#xff0c;可以是HBase Shell、Java API客户端、Rest API等&#xff0c;提供访问接口&#xff0c;并维护对应的缓存以加速HBase的访问。客户端缓存Region的位…

【设计模式】【创建型模式(Creational Patterns)】之抽象工厂模式(Abstract Factory Pattern)

1. 设计模式原理说明 工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类。这种模式的核心思想是将对象的创建过程封装起来,使得代码更加灵活和易于扩展。 优点: 符合开闭原则(对扩展开放,…

Ubuntu22.04配置强化学习环境及运行相关Demo

什么是强化学习 强化学习&#xff08;Reinforcement Learning&#xff0c;简称 RL&#xff09;是机器学习中的一个重要分支&#xff0c;属于一种基于试错机制的学习方法。它通过让智能体&#xff08;Agent&#xff09;与环境&#xff08;Environment&#xff09;进行交互&…

【jvm】为什么java是半编译半解释型语言

目录 1. 编译过程2. 解释过程3. 即时编译&#xff08;JIT&#xff09;过程4. 半编译半解释型语言的特点 1. 编译过程 1.Java源代码首先会被编译成字节码&#xff08;Bytecode&#xff09;&#xff0c;这是一种与具体平台无关的中间代码。2.这一编译过程由Java编译器&#xff0…

RUST学习教程-安装教程

文章目录 参考文档安装教程更新卸载 参考文档 https://course.rs/first-try/installation.html 安装教程 Linux或者mac安装教程 curl --proto https --tlsv1.2 https://sh.rustup.rs -sSf | sh安装完成&#xff0c;当出现command not found的时候&#xff0c;需要source一下…

网络安全 - DOS

1.1.1 摘要 最近网络安全成了一个焦点&#xff0c;除了国内明文密码的安全事件&#xff0c;还有一件事是影响比较大的——Hash Collision DoS&#xff08;通过Hash碰撞进行的拒绝式服务攻击&#xff09;&#xff0c;有恶意的人会通过这个安全漏洞让你的服务器运行巨慢无比&…

深入理解下oracle 11g block组成

深层次说&#xff0c;oracle数据库的最少组成单位应该是块&#xff0c;一般默认情况下&#xff0c;oracle数据库的块大小是8kb&#xff0c;其中存储着我们平常所需的数据。我们在使用过程中&#xff0c;难免会疑问道&#xff1a;“oracle数据块中到底是怎样组成的&#xff0c;平…