内容
# crashdx
[](https://github.com/r00tify/crashdx/actions/workflows/ci.yml)
一款适用于苹果平台的崩溃**诊断**引擎:解析`.ips`崩溃报告,与dSYM进行符号匹配,并生成有证据支持的、排名的诊断结果,而不仅仅是符号化的堆栈跟踪。
该引擎以无依赖的Swift库(`CrashDXCore`仅导入Foundation)、命令行工具(`crashdx`)和MCP服务器(`crashdx-mcp`)的形式提供,以便代理和人类使用相同的引擎。
## 为什么
符号化的堆栈跟踪告诉你进程在哪里终止,但不告诉你为什么。crashdx在符号化的基础上添加了第二阶段:确定性的、基于规则的证据提取(监视狗预算、jetsam表格、寄存器和内存状态、`lastExceptionBacktrace`/`asi`),并生成一组排名的竞争假设,每个假设都引用支持它的具体事实,并指向原始报告。
该引擎坚持两个特性:
- **每个声明都是可追溯的。** 事实携带一个指向原始报告的JSON路径,因此任何裁决都可以被检查而不是被信任。
- **当它是模糊的时,它会说“模糊”。** 裁决需要领先的假设被强烈支持 *并且* 明显领先于亚军;否则,你会得到排名的候选人和可以解决问题的条件。
引擎中没有LLM调用:它生成可验证的事实和排名的解释,并将叙述留给消费者。有关完整的架构,请参见 [docs/DESIGN.md](docs/DESIGN.md)。
## 要求
- macOS 14+
- **Swift 6.2+** 工具链。manifest本身是 `swift-tools-version:6.0`,但MCP服务器的固定依赖项声明高达 `6.2`,SwiftPM解析整个包图,因此6.2是每个目标(包括`CrashDXCore`)的实际最低要求。
- **Xcode** (不仅仅是命令行工具):符号化驱动苹果的 `CrashSymbolicator.py` 来自Xcode的 `CoreSymbolicationDT.framework`,通过 `xcode-select -p` 定位。没有它,crashdx会退回到 `atos`,它解析的源位置较少。解析和诊断无论哪种方式都有效。
- `/usr/bin/python3` 和 `/usr/bin/dwarfdump` (两者都由Xcode的命令行工具提供),用于运行 `CrashSymbolicator.py` 和验证dSYM UUID。
### 支持的报告
诚实的范围,因为一个崩溃诊断器在你的平台上悄悄地做得更差劲,不如一个说出来的诊断器:
- **arm64崩溃报告完全支持**:苹果硅Mac,iOS/iPadOS/watchOS/tvOS设备,以及托管在苹果硅上的模拟器。这是fixture corpus涵盖的内容。
- **x86_64报告** (Intel Mac,Rosetta翻译进程,Intel上的模拟器)解析和符号化,引擎读取 `x86_THREAD_STATE` 寄存器和4KB页面大小。corpus中没有Intel fixture,因此这条路径是推理的,而不是针对真实报告进行锻炼的。
- **仅崩溃报告** (`bug_type` 309/109)。jetsam事件报告(`JetsamEvent-*.ips`,`bug_type` 298)和挂起/堆栈快照报告(`bug_type` 288)使用不同的有效载荷形状,没有线程或异常对象;crashdx解析它们时没有错误,但没有事实可供使用,因此会报告模糊的。
### 隐私
crashdx完全在你的机器上运行,**不进行任何网络调用**。崩溃报告、dSYM和从它们导出的所有内容都保留在本地。这很重要,因为`.ips`文件包含识别数据(`crashReporterKey`、启动/睡眠-唤醒UUID、设备型号和路径中的用户名),因此如果你将其中一个附加到错误报告中,请先擦除它。
## 安装/构建
```sh
git clone https://github.com/r00tify/crashdx.git
cd crashdx
swift build -c release
```
二进制文件位于 `.build/release/`。要将它们放在你的 `PATH` 中:
```sh
sudo mkdir -p /usr/local/bin
sudo cp .build/release/crashdx .build/release/crashdx-mcp /usr/local/bin/
```
(或复制到你已经拥有的目录中,例如 `~/.local/bin`。)
## 用法
崩溃报告位于 `~/Library/Logs/DiagnosticReports/` 在macOS上(或Console.app → 崩溃报告);在iOS上,设置 → 隐私和安全 → 分析和改进 → 分析数据,以及Xcode的Organizer用于TestFlight/App Store崩溃。
```sh
crashdx analyze report.ips # 人类可读的摘要 + 诊断
crashdx analyze report.ips --json # 结构化的AnalysisReport JSON
crashdx analyze report.ips --json --tier full # ... 包含每个线程
crashdx symbolicate report.ips --dsym path/to.dSYM # 仅符号化,打印丰富的.ips
crashdx --version
```
`--dsym` 接受一个 `.dSYM` 包、一个 `.xcarchive` 或一个目录进行递归搜索(可重复),而 `--no-spotlight` 跳过基于Spotlight的发现,而 `--no-archives` 跳过Xcode的存档目录。运行 `crashdx <subcommand> --help` 获取完整的选项列表。注意, `--json` 和 `--tier` 仅适用于 `analyze`;`symbolicate` 始终发出完整的 `.ips`。
两个子命令都自动在Spotlight和Xcode的存档中搜索匹配的dSYM。对于外部报告(用户提交的、TestFlight、CI工件),请使用 `--dsym` 显式传递构建的dSYM。
从报告中提取的字符串(进程名称、符号、路径、异常文本)在人类可读的摘要打印之前会进行转义:C0控制字符、DEL和双向覆盖会渲染为 `\x0A` / `\u{202E}` 而不是被发出,因此精心构造的报告不能伪造 `DIAGNOSIS:` 行或重新绘制终端。 `--json` 和 `symbolicate` 发出报告的字符串原样;将它们的输出视为数据,而不是终端文本。
来自 **不同** 构建的dSYM会被拒绝而不是使用:过时的dSYM会产生自信的错误符号,这比没有符号更糟糕。这种情况被报告为 `uuid_mismatch` (带有 `reason` 中的违规路径),与 `no_dsym` 区分开来,因为修复方法不同:找到与报告的构建UUID匹配的存档,而不是寻找你可能已经拥有的文件。
### 报告层级
`--tier` 控制报告的发出内容;它永远不会改变诊断结果,诊断结果始终根据完整的报告计算:
| 层级 | 内容 |
|---|---|
| `summary` (默认) | 故障线程(上限15帧),`lastExceptionBacktrace`,以及诊断裁决 + 排名假设 |
| `standard` | 提升帧上限,并添加二进制镜像、包含应用帧的其他线程和 `factsConsidered` (每个假设的证据) |
| `full` | 添加所有剩余线程,包括没有应用帧的线程 |
### 退出代码
`0` 成功 · `64` 用法错误 · `65` 输入无法解析为 `.ips` 报告,或符号化失败 · `66` 文件未找到或不可读。
诊断信息输出到stderr;标准输出携带报告输出(和 `--help`/`--version`)。
### MCP服务器
`crashdx-mcp` 通过stdio(换行JSON-RPC)公开与 `crashdx_analyze` 和 `crashdx_symbolicate` 工具相同的管道。使用Claude Code:
```sh
claude mcp add crashdx /usr/local/bin/crashdx-mcp
```
一个匹配的 `crash-triage` 代理技能包含在 `.claude/skills/crash-triage/` 中,涵盖了如何阅读诊断结果和特定于每个崩溃系列的解释陷阱。
### 作为库
将 `https://github.com/r00tify/crashdx.git` 添加到你的 `Package.swift` 中,依赖于 `CrashDXCore` 产品,并调用
`AnalyzePipeline.analyze(path:tier:dsymPaths:useSpotlight:searchArchives:)`,这是两个二进制文件使用的相同入口点。
`CrashDXCore` 仅导入 `Foundation`,但有两个限制需要注意:
- **它是macOS独有的。** 符号化通过 `Foundation.Process` 调用 `atos`/`dwarfdump`/`mdfind`,而 `Foundation.Process` 在iOS上不存在。将此包添加到iOS目标会在依赖项解析期间失败,在编译任何内容之前。
- SwiftPM解析整个包图,而不是单个产品,因此依赖此包会将MCP服务器的依赖项(swift-sdk及其传递的NIO/collections/log包)固定在你的 `Package.resolved` 中,即使你从未导入它们。
`AnalysisReport` 和诊断模型是 `Sendable` 的,因此并行分析报告目录的工作如预期。
## 项目布局
```
Sources/CrashDXCore/ 解析、符号化和诊断引擎(仅导入Foundation)
Sources/crashdx/ 命令行工具
Sources/crashdx-mcp/ MCP服务器(依赖swift-sdk)
Tests/ 单元测试 + 集成测试、黄金快照、崩溃fixtures
corpus/ 基础崩溃fixtures及其已验证的结果
docs/DESIGN.md 诊断引擎架构
Scripts/ fixtures清理和CI隐私保护
```
## 测试
```sh
swift test
```
## 贡献
参见 [CONTRIBUTING.md](CONTRIBUTING.md)。有一条规则比其他规则更重要:**崩溃报告和dSYM必须在提交之前进行清理**。它们包含设备标识符和你的用户名。 `Scripts/scrub-fixture.py` 处理 `.ips` 文件,而 `Scripts/check-fixtures-scrubbed.sh` (也在CI中运行)会告诉你是否有任何文件被漏掉了。
## 安全和隐私
crashdx不进行网络调用;没有任何内容离开你的机器。参见 [SECURITY.md](SECURITY.md) 以获取有关漏洞报告和 `.ips` 文件实际内容的说明,然后再分享。
## 许可证
MIT。参见 [LICENSE](LICENSE)。