7个版本
0.2.1 | 2022年7月6日 |
---|---|
0.2.0 | 2022年3月10日 |
0.1.4 | 2022年1月12日 |
0.1.3 | 2021年12月8日 |
0.1.2 | 2021年11月23日 |
#728 in 调试
每月 30次下载
81KB
1.5K SLoC
sock-pair
用于测试、调试和基准测试rust-minidump的minidump-stackwalk的测试框架,特别针对Firefox崩溃报告进行了优化。
最初设计是为了检查rust-minidump的输出是否与Mozilla在生产环境中运行的breakpad分支相同(或更好)。但由于现在rust-minidump是生产实现,它已经发展成为一个帮助你
- 深入了解Firefox崩溃报告的内容
- minidump中的实际值是什么?
- 让我们通过一个新实验性分析步骤来测试这一点!
- 调试rust-minidump产生特定值的原因
- 为什么回溯在这里没有使用CFI?
- 它对此minidump产生任何警告吗?
- 对“真实”输入进行本地更改的测试和基准测试
- 哎呀,我意外地破坏了这个模式中的字段!
- 嘿,在这种情况下,它使用了10%更少的内存!
用法
socc-pair --minidump=/path/to/minidump.dmp
or for mozilla crash reports:
socc-pair --api-token=YOUR_TOKEN --crash-id=SOME_CRASH_ID
例如:
socc-pair --minidump=C:\wow\cool\minidump.dmp
or for mozilla crash reports:
socc-pair --api-token=f0c129d4467bf58eeca0ad8e8e5d --crash-id=cd121a28-ca2b-48c2-a0d4-a71a40210915
这将自动运行给定minidump上的minidump-stackwalk,并生成执行详细报告。
注意,默认情况下,我们将为你自动安装cargo install minidump-stackwalk
。这始终会在本地临时位置(例如/tmp/socc-pair
或target
)完成。有关替代方案,请参阅--run-local
。
Mozilla Socorro (crash-stats.mozilla.org) 集成
本节涵盖socco模式(--crash-id=... --api-token=...
)。
Socco模式将产生两个json文件之间的某种差异,但具有更智能的特定领域分析。在输出末尾,您将获得错误和警告的最终计数,以及所有不同输入/输出文件的路径。
您需要一个具有以下权限的socco API密钥
- "查看原始转储"
- "查看个人信息"(以读取原始json中的某些条目)
如果您不想使用第二个权限,可以将 --raw-json=none
设置为跳过原始 JSON。
重要可选参数
--run-local=path
- 指定 socc-pair 应该编译和使用 rust-minidump-stackwalk 检出的路径。--bench=times
- 运行 minidump-stackwalk 指定次数以进行基准测试。--output-file=path
- 将所有输出写入文件(如果将其保存为 .diff,编辑器将为 json 差异提供语法高亮!)。--clean-cache
- 清除所有缓存,包括每次基准测试迭代之前的符号缓存(小心!)。--skip-diff
- 禁用 JSON 差异比较(当你专注于基准测试时很有用)。--no-symbols
- 防止 minidump-stackwalk 获取任何符号文件,以测试该情况。--mock-server
- 创建本地符号服务器以测试网络连接,而无需关闭互联网。--cyborg
- 从 minidump-stackwalk 产生 --human 和 --json 输出。
执行示例
socc-pair 设计用于测试本地更改的影响。这里我们通过以下方式真正发挥该能力:
- 从 socorro 下载我们认为有趣的 minidump(默认)
- 编译并使用 rust-minidump 的本地检出,以测试我们的更改
- 使用 mozilla 的符号服务器进行符号化和展开 (默认)
- 将本地结果与生产中的值进行差异比较 (默认)
- 通过反复运行 minidump-stackwalk 来基准测试本地更改
- 将所有中间结果保存到文件中,以便我们可以调试任何问题 (默认)
- 将所有内容重定向到“diff”文件以在报告中获得语法高亮
(注意,通过启用基准测试,我们将自动禁用堆栈展开跟踪日志。这使得结果更准确地反映生产配置,但这也意味着您可能需要在调试堆栈展开时停止基准测试。)
socc-pair
--api-token=f0c129d4467bf58eeca0ad8e8e5d
--crash-id=b4f58e9f-49be-4ba5-a203-8ef160211027
--build-local=/Users/ABeingessner/dev/rust-minidump/minidump-stackwalk/
--bench=5
--output-file=output.diff
NOTE: setting minidump-stackwalk --verbose to 'error' for benchmarking
Had cached 082a152f-05b4-4de9-943b-c30550211210.dmp
Had cached 082a152f-05b4-4de9-943b-c30550211210.json
Had cached 082a152f-05b4-4de9-943b-c30550211210.raw.json
building local minidump-stackwalk...
Finished release [optimized] target(s) in 0.11s
built /Users/ABeingessner/dev/rust-minidump/target/release/minidump-stackwalk
running local minidump-stackwalk... (5 times)
done! (1/5)
done! (2/5)
done! (3/5)
done! (4/5)
done! (5/5)
all done!
comparing json...
: {
crash_info: {
address: 0x7fff1760aca0
crashing_thread: 8
type: EXCEPTION_BREAKPOINT
}
crashing_thread: {
frames: [
0: {
file: hg:hg.mozilla.org/mozilla-central:mozglue/static/rust/wrappers.cpp:1750da2d7f9db490b9d15b3ee696e89e6aa68cb7
frame: 0
function: RustMozCrash(char const*, int, char const*)
function_offset: 0x00000010
- did not match
+ line: 17
- line: 20
module: xul.dll
.....
.....
.....
unloaded_modules: [
0: {
base_addr: 0x7fff48290000
- local val was null instead of:
code_id: 68798D2F9000
end_addr: 0x7fff48299000
filename: KBDUS.DLL
}
1: {
base_addr: 0x7fff56020000
code_id: DFD6E84B14000
end_addr: 0x7fff56034000
filename: resourcepolicyclient.dll
}
]
~ ignoring field write_combine_size: "0"
}
- Total errors: 288, warnings: 39
benchmark results (ms):
2388, 1986, 2268, 1989, 2353,
average runtime: 00m:02s:196ms (2196ms)
median runtime: 00m:02s:268ms (2268ms)
min runtime: 00m:01s:986ms (1986ms)
max runtime: 00m:02s:388ms (2388ms)
max memory (rss) results (bytes):
267755520, 261152768, 272441344, 276131840, 279134208,
average max-memory: 258MB (271323136 bytes)
median max-memory: 259MB (272441344 bytes)
min max-memory: 249MB (261152768 bytes)
max max-memory: 266MB (279134208 bytes)
Output Files:
* (download) Minidump: C:\Users\gankra\AppData\Local\Temp\socc-pair\dumps\b4f58e9f-49be-4ba5-a203-8ef160211027.dmp
* (download) Socorro Processed Crash: C:\Users\gankra\AppData\Local\Temp\socc-pair\dumps\b4f58e9f-49be-4ba5-a203-8ef160211027.json
* (download) Raw JSON: C:\Users\gankra\AppData\Local\Temp\socc-pair\dumps\b4f58e9f-49be-4ba5-a203-8ef160211027.raw.json
* Local minidump-stackwalk --json Output: C:\Users\gankra\AppData\Local\Temp\socc-pair\dumps\b4f58e9f-49be-4ba5-a203-8ef160211027.local.json
* Local minidump-stackwalk Logs: C:\Users\gankra\AppData\Local\Temp\socc-pair\dumps\b4f58e9f-49be-4ba5-a203-8ef160211027.log.txt
调试回溯
请参阅 上游调试文档。
socc-pair 将捕获并存储 rust-minidump 的日志输出(请参阅上述示例末尾的“Local minidump-stackwalk Logs”路径)。socc-pair 还将 rust-minidump 配置为默认使用 trace
日志记录,它包括对每次堆栈展开的详细跟踪。
(如果日志记录行为异常,可以使用 --verbose
进行配置)
关于阅读这些日志的一些建议
- 所有展开行都将以
[TRACE] unwind
开头(其他日志可能被插入)。 - 每个线程的展开将
- 以 "starting stack unwind" 开始
- 以 "finished stack unwind" 结束
- 每个帧的展开将
- 以 "unwinding <name>" 开始
- 以 "<unwinding method> seems valid" 结束
- 在末尾包含最终指令指针和栈指针的值
- 尝试展开的方法按顺序尝试(质量递减)
- cfi
- 帧指针
- 扫描
如果您看到 "trying scan" 或 "trying framepointer",这意味着之前的展开方法失败了。有时失败的原因会被记录下来,但有时失败的地方很奇怪,我没有记录任何日志。如果发生这种情况,您仍然可以根据通常在该步骤之后发生的事情来推断可能出了什么问题。
例如,cfi 跟踪通常看起来像这样
[TRACE] unwind: unwinding NtGetContextThread
[TRACE] unwind: trying cfi
[TRACE] unwind: found symbols for address, searching for cfi entries
如果您看到
[TRACE] unwind: unwinding NtGetContextThread
[TRACE] unwind: trying cfi
[TRACE] unwind: trying frame pointer
这表明cfi分析甚至无法到达“找到地址的符号”。因此,很可能是它无法找到当前指令指针的符号。这可能是因为它没有映射到已知模块,或者因为该模块没有符号。
示例跟踪
[TRACE] unwind: starting stack unwind
[TRACE] unwind: unwinding NtGetContextThread
[TRACE] unwind: trying cfi
[TRACE] unwind: found symbols for address, searching for cfi entries
[TRACE] unwind: trying STACK CFI exprs
[TRACE] unwind: .cfa: $rsp 8 + .ra: .cfa 8 - ^
[TRACE] unwind: .cfa: $rsp 8 +
[TRACE] unwind: STACK CFI parse successful
[TRACE] unwind: STACK CFI seems reasonable, evaluating
[TRACE] unwind: successfully evaluated .cfa (frame address)
[TRACE] unwind: successfully evaluated .ra (return address)
[TRACE] unwind: cfi evaluation was successful -- caller_ip: 0x000000ec00000000, caller_sp: 0x000000ec7fbfd790
[TRACE] unwind: cfi result seems valid
[TRACE] unwind: unwinding 1013612281855
[TRACE] unwind: trying cfi
[TRACE] unwind: trying frame pointer
[TRACE] unwind: trying scan
[TRACE] unwind: scan seems valid -- caller_ip: 0x7ffd172c2a24, caller_sp: 0xec7fbfd7f8
[TRACE] unwind: unwinding <unknown in ntdll.dll>
[TRACE] unwind: trying cfi
[TRACE] unwind: found symbols for address, searching for cfi entries
[TRACE] unwind: trying frame pointer
[TRACE] unwind: trying scan
[TRACE] unwind: scan seems valid -- caller_ip: 0x7ffd162b7034, caller_sp: 0xec7fbfd828
[TRACE] unwind: unwinding BaseThreadInitThunk
[TRACE] unwind: trying cfi
[TRACE] unwind: found symbols for address, searching for cfi entries
[TRACE] unwind: trying STACK CFI exprs
[TRACE] unwind: .cfa: $rsp 8 + .ra: .cfa 8 - ^
[TRACE] unwind: .cfa: $rsp 48 +
[TRACE] unwind: STACK CFI parse successful
[TRACE] unwind: STACK CFI seems reasonable, evaluating
[TRACE] unwind: successfully evaluated .cfa (frame address)
[TRACE] unwind: successfully evaluated .ra (return address)
[TRACE] unwind: cfi evaluation was successful -- caller_ip: 0x0000000000000000, caller_sp: 0x000000ec7fbfd858
[TRACE] unwind: cfi result seems valid
[TRACE] unwind: instruction pointer was nullish, assuming unwind complete
[TRACE] unwind: finished stack unwind
依赖关系
~11-25MB
~409K SLoC