apple-crash-symbolication
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseApple Platform Crash Log .NET Symbolication
苹果平台崩溃日志的.NET符号化解析
Resolves native backtrace frames from .NET MAUI and Mono app crashes on Apple platforms (iOS, tvOS, Mac Catalyst, macOS) to function names, source files, and line numbers using Mach-O UUIDs and dSYM debug symbol bundles.
Inputs: Crash log file ( JSON format, iOS 15+ / macOS 12+), (from Xcode), optionally a connected iOS device to pull crash logs from.
.ipsatosDo not use when: The crashing library is not a .NET component (e.g., pure Swift/UIKit), or the crash log is an Android tombstone.
通过Mach-O UUID和dSYM调试符号包,将苹果平台(iOS、tvOS、Mac Catalyst、macOS)上.NET MAUI和Mono应用崩溃的原生回溯帧解析为函数名、源文件及行号。
输入:崩溃日志文件( JSON格式,iOS 15+ / macOS 12+)、(来自Xcode),可选已连接的iOS设备用于拉取崩溃日志。
.ipsatos不适用场景:崩溃库并非.NET组件(如纯Swift/UIKit),或崩溃日志为Android tombstone文件。
Workflow
工作流程
Step 1: Parse the .ips Crash Log
步骤1:解析.ips崩溃日志
Format check: Before proceeding, verify the file is JSON format. The first line must be valid JSON. If the file is plain text (e.g., Android tombstone with frame lines, or legacy Apple text format), stop immediately — this workflow does not apply. Report the format mismatch to the user and do not attempt any symbolication.
.ips#NN pc.crashThe file is two-part JSON: line 1 is a metadata header; the remaining lines are a separate JSON crash body. Parse them separately:
.ipspython
lines = open('crash.ips').readlines()
metadata = json.loads(lines[0]) # app_name, bundleID, os_version, slice_uuid
crash = json.loads(''.join(lines[1:])) # Full crash reportKey fields in the crash body:
- has
usedImages[N],name(load address),base,uuidfor each loaded binaryarch - has
threads[N].frames[M],imageOffset; frame address =imageIndexusedImages[imageIndex].base + imageOffset - ,
exception.type(e.g.,exception.signal/EXC_CRASH)SIGABRT - (Application Specific Information) often contains the managed exception message
asi - has frames from the exception that triggered the crash
lastExceptionBacktrace - is the index into the
faultingThreadarraythreads
Parsing gotcha: Some .ips files have case-conflicting duplicate keys ( / ). Pre-process the raw JSON to rename the lowercase duplicate before parsing. The field may be absent.
vmRegionInfovmregioninfoasi格式检查:在开始前,验证文件为 JSON格式。第一行必须是有效的JSON。如果文件是纯文本格式(例如带有帧行的Android tombstone,或旧版苹果文本格式),请立即停止——本工作流程不适用。向用户报告格式不匹配问题,不要尝试任何符号化解析操作。
.ips#NN pc.crash.ipspython
lines = open('crash.ips').readlines()
metadata = json.loads(lines[0]) # app_name, bundleID, os_version, slice_uuid
crash = json.loads(''.join(lines[1:])) # 完整崩溃报告崩溃主体中的关键字段:
- 包含每个已加载二进制文件的
usedImages[N]、name(加载地址)、base、uuidarch - 包含
threads[N].frames[M]、imageOffset;帧地址 =imageIndexusedImages[imageIndex].base + imageOffset - 、
exception.type(例如exception.signal/EXC_CRASH)SIGABRT - (应用特定信息)通常包含托管异常消息
asi - 包含触发崩溃的异常调用栈帧
lastExceptionBacktrace - 是
faultingThread数组中的索引threads
解析注意事项:部分.ips文件存在大小写冲突的重复键( / )。解析前需预处理原始JSON,重命名小写的重复键。字段可能不存在。
vmRegionInfovmregioninfoasiStep 2: Identify .NET Runtime Libraries
步骤2:识别.NET运行时库
Filter to .NET runtime libraries:
usedImages| Library | Runtime |
|---|---|
| CoreCLR runtime |
| Mono runtime |
| .NET BCL native component |
| .NET BCL globalization |
| .NET BCL crypto |
| .NET BCL compression |
| .NET BCL net security |
On Apple platforms these ship as bundles, so image names may omit . Match using substring (e.g., not ). The app binary may appear twice in with different UUIDs.
.framework.dyliblibcoreclrlibcoreclr.dylibusedImagesKey bridge functions in the app binary: (managed exception bridged to ObjC NSException), , , .
xamarin_process_managed_exceptionxamarin_mainmono_jit_execcoreclr_execute_assemblyNativeAOT: Runtime is statically linked into the app binary. BCL libraries remain separate. The app binary needs its own dSYM from the build output.
libSystem.*Skip , , and other Apple system frameworks unless specifically asked.
libsystem_kernel.dylibUIKitCore从中筛选出.NET运行时库:
usedImages| 库名称 | 运行时环境 |
|---|---|
| CoreCLR运行时 |
| Mono运行时 |
| .NET BCL原生组件 |
| .NET BCL全球化组件 |
| .NET BCL加密组件 |
| .NET BCL压缩组件 |
| .NET BCL网络安全组件 |
在苹果平台上,这些库以包形式发布,因此镜像名称可能省略。需通过子字符串匹配(例如匹配而非)。应用二进制文件可能在中出现两次且UUID不同。
.framework.dyliblibcoreclrlibcoreclr.dylibusedImages应用二进制文件中的关键桥接函数:(托管异常桥接到ObjC NSException)、、、。
xamarin_process_managed_exceptionxamarin_mainmono_jit_execcoreclr_execute_assemblyNativeAOT:运行时静态链接到应用二进制文件中。 BCL库仍为独立文件。应用二进制文件需要其构建输出中的专属dSYM。
libSystem.*除非特别要求,否则跳过、及其他苹果系统框架。
libsystem_kernel.dylibUIKitCoreStep 3: Interpret the Crash
步骤3:分析崩溃原因
Start with (Application Specific Information) — for .NET crashes, it often contains the managed exception type and message (e.g., , ). The root cause may already be visible here.
asiXamlParseExceptionNullReferenceExceptionThen examine the faulting thread (). Explain what frames #0 and #1 mean before examining other threads. Cross-thread context (GC state, thread pool) is useful for validation but not evidence of causation.
threads[faultingThread]Also check for the managed exception path through bridge functions like .
lastExceptionBacktracexamarin_process_managed_exceptionSometimes the .NET runtime version is visible in image paths in , particularly on macOS when using shared-framework installs or NuGet-pack-style layouts (e.g., ). On iOS, however, image paths are typically inside the app bundle (for example, ) and do not embed the runtime version, so you usually need to infer it via the Mach-O UUID by matching against SDK packs or symbol-server downloads rather than relying on the path alone.
usedImages.../Microsoft.NETCore.App/10.0.4/libcoreclr.dylib.../Frameworks/libcoreclr.framework/libcoreclr首先查看字段(应用特定信息)——对于.NET崩溃,它通常包含托管异常类型和消息(例如、)。根本原因可能已在此处显现。
asiXamlParseExceptionNullReferenceException然后检查故障线程()。在分析其他线程前,先解释帧#0和#1的含义。跨线程上下文(GC状态、线程池)可用于验证,但不能作为因果证据。
threads[faultingThread]同时检查,查看通过等桥接函数的托管异常调用路径。
lastExceptionBacktracexamarin_process_managed_exception有时可在的镜像路径中看到.NET运行时版本,尤其是在macOS上使用共享框架安装或NuGet包布局时(例如)。但在iOS上,镜像路径通常位于应用包内(例如),且不嵌入运行时版本,因此通常需要通过Mach-O UUID与SDK包或符号服务器下载内容匹配来推断版本,而非依赖路径。
usedImages.../Microsoft.NETCore.App/10.0.4/libcoreclr.dylib.../Frameworks/libcoreclr.framework/libcoreclrStep 4: Locate dSYMs
步骤4:定位dSYM
For each .NET library needing symbolication, locate a UUID-matched dSYM:
- Microsoft symbol server (automatic): Download via
.dwarf(UUID lowercase, no dashes). Convert tohttps://msdl.microsoft.com/download/symbols/_.dwarf/mach-uuid-sym-{UUID}/_.dwarfbundle (use the image name from.dSYM, e.g.,usedImages[].name):libcoreclrbashmkdir -p libcoreclr.dSYM/Contents/Resources/DWARF cp _.dwarf libcoreclr.dSYM/Contents/Resources/DWARF/libcoreclr - Build output:
bin/Debug/net*-ios/ios-arm64/<App>.app.dSYM/ - SDK packs:
$DOTNET_ROOT/packs/Microsoft.NETCore.App.Runtime.<rid>/<version>/runtimes/<rid>/native/ - NuGet cache:
~/.nuget/packages/microsoft.netcore.app.runtime.<rid>/<version>/runtimes/<rid>/native/ - :
dotnet-symboldotnet-symbol --symbols -o symbols-out <path-to-binary.dylib>
Always verify: must match the UUID from the crash log exactly.
dwarfdump --uuid <dsym>对于每个需要符号化解析的.NET库,找到匹配UUID的dSYM:
- Microsoft符号服务器(自动):通过下载
https://msdl.microsoft.com/download/symbols/_.dwarf/mach-uuid-sym-{UUID}/_.dwarf文件(UUID需小写,无连字符)。转换为.dwarf包(使用.dSYM中的镜像名称,例如usedImages[].name):libcoreclrbashmkdir -p libcoreclr.dSYM/Contents/Resources/DWARF cp _.dwarf libcoreclr.dSYM/Contents/Resources/DWARF/libcoreclr - 构建输出:
bin/Debug/net*-ios/ios-arm64/<App>.app.dSYM/ - SDK包:
$DOTNET_ROOT/packs/Microsoft.NETCore.App.Runtime.<rid>/<version>/runtimes/<rid>/native/ - NuGet缓存:
~/.nuget/packages/microsoft.netcore.app.runtime.<rid>/<version>/runtimes/<rid>/native/ - 工具:
dotnet-symboldotnet-symbol --symbols -o symbols-out <path-to-binary.dylib>
务必验证:必须与崩溃日志中的UUID完全匹配。
dwarfdump --uuid <dsym>Step 5: Symbolicate with atos
步骤5:使用atos进行符号化解析
bash
atos -arch arm64 -o <path.dSYM/Contents/Resources/DWARF/binary_name> -l <load_address> <frame_addresses...>- points to the DWARF binary inside the
-obundle (.dSYM), not the bundle itselfContents/Resources/DWARF/ - is the load address from
-lusedImages[N].base - Use the from
arch(usuallyusedImages[N].arch, may bearm64)arm64e - Pass multiple addresses per invocation for batch symbolication
bash
undefinedbash
atos -arch arm64 -o <path.dSYM/Contents/Resources/DWARF/binary_name> -l <load_address> <frame_addresses...>- 指向
-o包内部的DWARF二进制文件(.dSYM),而非包本身Contents/Resources/DWARF/ - 是
-l中的加载地址usedImages[N].base - 使用中的架构(通常为
usedImages[N].arch,可能为arm64)arm64e - 一次调用可传入多个地址进行批量符号化解析
bash
undefinedExample: symbolicate libcoreclr frames
示例:对libcoreclr帧进行符号化解析
atos -arch arm64 -o libcoreclr.dSYM/Contents/Resources/DWARF/libcoreclr -l 0x104000000 0x104522098 0x1043c0014
Strip the `/__w/1/s/` CI workspace prefix from output — meaningful paths start at `src/runtime/`, mapping to the [dotnet/dotnet](https://github.com/dotnet/dotnet) VMR.atos -arch arm64 -o libcoreclr.dSYM/Contents/Resources/DWARF/libcoreclr -l 0x104000000 0x104522098 0x1043c0014
从输出中去除`/__w/1/s/` CI工作区前缀——有意义的路径从`src/runtime/`开始,对应[dotnet/dotnet](https://github.com/dotnet/dotnet) VMR。Automation Script
自动化脚本
scripts/Symbolicate-Crash.ps1 automates the full workflow (parsing, dSYM lookup, symbol download, and symbolication). Resolve the path relative to this SKILL.md file.
powershell
undefinedscripts/Symbolicate-Crash.ps1可自动化完成整个工作流程(解析、dSYM查找、符号下载、符号化解析)。请相对于本SKILL.md文件解析路径。
powershell
undefined$SKILL_DIR is the directory containing this SKILL.md
$SKILL_DIR是包含本SKILL.md的目录
pwsh "$SKILL_DIR/scripts/Symbolicate-Crash.ps1" -CrashFile MyApp-2026-02-25.ips
Start with `-ParseOnly` for a fast overview without requiring `atos`. The script automatically downloads symbols from the Microsoft symbol server when local dSYMs are missing.
Flags: `-CrashingThreadOnly`, `-OutputFile path`, `-ParseOnly`, `-SkipVersionLookup`, `-SkipSymbolDownload`, `-SymbolCacheDir path`, `-DsymSearchPaths path1,path2`.
---pwsh "$SKILL_DIR/scripts/Symbolicate-Crash.ps1" -CrashFile MyApp-2026-02-25.ips
可先使用`-ParseOnly`参数快速概览,无需依赖`atos`。当本地dSYM缺失时,脚本会自动从Microsoft符号服务器下载符号。
可用参数:`-CrashingThreadOnly`, `-OutputFile path`, `-ParseOnly`, `-SkipVersionLookup`, `-SkipSymbolDownload`, `-SymbolCacheDir path`, `-DsymSearchPaths path1,path2`。
---Retrieving Crash Logs
获取崩溃日志
Pull crash logs from a connected iOS device using (from libimobiledevice):
idevicecrashreportbash
idevicecrashreport -e /tmp/crashlogs/
find /tmp/crashlogs/ -iname '*MyApp*' -name '*.ips'Also available in Xcode > Window > Devices and Simulators > View Device Logs, or at (Mac Catalyst), (macOS).
~/Library/Logs/CrashReporter/~/Library/Logs/DiagnosticReports/使用(来自libimobiledevice)从已连接的iOS设备拉取崩溃日志:
idevicecrashreportbash
idevicecrashreport -e /tmp/crashlogs/
find /tmp/crashlogs/ -iname '*MyApp*' -name '*.ips'也可通过Xcode > 窗口 > 设备与模拟器 > 查看设备日志获取,或在以下路径查找:(Mac Catalyst)、(macOS)。
~/Library/Logs/CrashReporter/~/Library/Logs/DiagnosticReports/Validation
验证
- matches UUID from the crash log
dwarfdump --uuid <dsym> - At least one .NET frame resolves to a function name (not a raw address)
- Resolved paths contain recognizable .NET runtime structure (e.g., ,
src/coreclr/,mono/metadata/)mono/mini/
- 与崩溃日志中的UUID匹配
dwarfdump --uuid <dsym> - 至少有一个.NET帧解析为函数名(而非原始地址)
- 解析后的路径包含可识别的.NET运行时结构(例如,
src/coreclr/,mono/metadata/)mono/mini/
Stop Signals
终止信号
- Wrong file format: If the file is not JSON (e.g., Android tombstone with
.ipsstack frames, legacy#NN pctext format), stop immediately — report the format mismatch to the user and do not proceed with any symbolication. Do not attempt to symbolicate using other tools or workflows..crash - No .NET frames found: Report parsed frames and stop.
- All frames resolved: Present symbolicated backtrace with brief crash analysis (faulting thread, exception type, likely area). If the user asks for deeper investigation, proceed.
- dSYM not available / UUID mismatch: Report unsymbolicated frames with UUIDs and addresses. Suggest locating the original build artifacts.
- atos not available: Present the manual commands for the user to run. Do not install Xcode.
atosships with Xcode Command Line Tools (atos).xcode-select --install
- 文件格式错误:如果文件不是JSON格式(例如带有
.ips调用栈帧的Android tombstone、旧版#NN pc文本格式),请立即停止——向用户报告格式不匹配问题,不要继续任何符号化解析操作。不要尝试使用其他工具或工作流程进行符号化解析。.crash - 未找到.NET帧:报告解析后的帧并停止。
- 所有帧已解析:展示符号化后的回溯信息及简要崩溃分析(故障线程、异常类型、可能的问题区域)。如果用户要求深入调查,再继续。
- dSYM不可用/UUID不匹配:报告未符号化的帧及其UUID和地址。建议用户定位原始构建产物。
- atos不可用:提供手动运行的命令供用户执行。不要安装Xcode。
atos随Xcode命令行工具一起发布(atos)。xcode-select --install
References
参考资料
- IPS format details: See references/ips-crash-format.md for additional .ips parsing details and macOS symbol package differences.
- IPS格式详情:查看references/ips-crash-format.md获取更多.ips解析细节及macOS符号包差异。