尧图精选

在 Unix 上调试 .NET 核心库:lldb 与 SOS 实战指南(runtime 仓库)

🕒 发布时间:2026/9/20 5:03:42 📁 来源:尧图网络
在 Unix 上调试 .NET 核心库lldb 与 SOS 实战指南runtime 仓库【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址: https://gitcode.com/GitHub_Trending/runtime6/runtime导读本文基于 dotnet/runtime 仓库的 docs/workflow/debugging/libraries/unix-instructions.md 编写面向需要在 Linux/macOS 等 Unix 平台上调试 .NET 核心库CoreCLR、System.Private.CoreLib 及各托管库的开发者系统讲解使用 lldb SOS 进行源码级调试、以及利用createdump生成并分析崩溃转储core dump的完整工作流。读完本文你将掌握如何安装配置 SOS 与 lldb、如何用/t:Test目标跑通测试以便附加调试、如何让 lldb 正确解析libcoreclr.so的符号、如何配置环境变量触发崩溃转储以及如何对核心库测试崩溃产生的 dump 做栈回溯与托管状态分析。调试方法总览在 Unix 平台上调试 .NET 核心库官方支持两条技术路线lldb SOS通过 SOS 调试器扩展在 lldb 中查看托管状态托管调用栈、对象、GC 堆等适合日常源码级调试与测试失败分析Visual Studio Code利用 C# 调试适配器与lldb配合的交互式调试体验详见 debugging-vscode.md。本文以 lldb SOS 为主线因为它是分析核心库崩溃、尤其是分析 core dump 时最直接的工具链。使用 lldb 与 SOS 调试安装 lldb 与 SOS在开始调试之前需要准备两样东西lldbLLVM 调试器用于加载可执行文件与 core dump提供符号解析和原生层栈回溯SOS 调试器扩展负责在 lldb 内部理解 .NET 运行时与托管代码。SOS 的安装方式在不同版本/发行版上有差异官方安装指引见 dotnet/diagnostics 仓库的documentation/sos.md也可以通过dotnet tool install -g dotnet-sos安装dotnet-sos全局工具然后运行dotnet-sos install将 SOS 加载进 lldb。dotnet-sos工具同时支持dotnet-sos uninstall、dotnet-sos sethostruntime等子命令用于管理调试器扩展的加载状态。先用 msbuild 跑通测试关键前置步骤这是整个调试流程中最容易被忽略、却至关重要的一步在尝试附加调试之前先用 msbuild 以/t:Test目标运行至少一次测试。./build.sh -subset libs /t:Test /p:testscope库名 # 或针对具体测试项目 ./dotnet.sh build 测试项目路径 /t:Test这样做的原因是coreclr 的库测试编译产物包括libcoreclr.so、对应的.so.dbg符号文件以及各程序集会被布局到特定的输出目录而调试器后续要解析的符号路径与这些产物强相关。先跑通一次测试可以保证所有需要调试的程序集与原生符号文件已生成并处于正确位置后续用 lldb 加载时settings set target.exec-search-paths指向的runtime-path目录存在且内容完整。仓库中相关调试说明可参考 debugging-corelib.md 与 debugging-runtime.md。用 lldb 调试 core dump除了附加到正在运行的进程更常见的核心库调试场景是事后分析崩溃转储。要完成一次成功的 dump 调试需要准备以下三样东西必备项说明崩溃转储文件core dump崩溃时生成的转储文件路径与命名方式由 dump 配置决定createdump工具在 Linux 上运行时内置的createdump工具可以在托管应用抛未捕获异常或发生 fault 时自动生成 core dump详见 xplat-minidump-generation.mdlldb SOS已按上文安装配置好的调试工具链让 lldb 正确解析 libcoreclr.so 的符号关键一步是加载 core dump 时必须给 lldb 额外指定target.exec-search-paths否则 lldb 无法定位libcoreclr.so对应的符号文件栈回溯会退化为无符号的裸地址。标准命令格式如下lldb-3.9 -O settings set target.exec-search-paths runtime-path --core core-file-path host-path三个占位符的含义runtime-path包含libcoreclr.so.dbg以及其余运行时与框架程序集的目录路径core-file-path要调试的 core dump 文件路径host-pathdotnet或corerun可执行文件的路径通常就位于runtime-path目录中。执行成功后lldb 会以符号已解析的状态进入调试会话此时btbacktrace可以看到带libcoreclr.so符号的栈帧。接着只要 SOS 已按前述指引加载就可以开始使用clrstack、pe、dumpheap等一系列 SOS 命令分析托管状态。完整示例原文档给出了一个来自 CIHelix环境的真实示例其中 dump 是 Helix 测试机在跑System.Drawing.Common.Tests时崩溃产生的路径结构完整展示了三个参数的实际形态lldb-3.9 -O settings set target.exec-search-paths /home/parallels/Downloads/System.Drawing.Common.Tests/home/helixbot/dotnetbuild/work/2a74cf82-3018-4e08-9e9a-744bb492869e/Payload/shared/Microsoft.NETCore.App/$(ProductVersion)/ --core /home/parallels/Downloads/System.Drawing.Common.Tests/home/helixbot/dotnetbuild/work/2a74cf82-3018-4e08-9e9a-744bb492869e/Work/f6414a62-9b41-4144-baed-756321e3e075/Unzip/core /home/parallels/Downloads/System.Drawing.Common.Tests/home/helixbot/dotnetbuild/work/2a74cf82-3018-4e08-9e9a-744bb492869e/Payload/shared/Microsoft.NETCore.App/$(ProductVersion)/dotnet可以看到--core指向Work/.../Unzip/core即 Helix 工作项解压目录下的 core 文件exec-search-paths与host-path都指向Payload/shared/Microsoft.NETCore.App/$(ProductVersion)/其中$(ProductVersion)是运行时产品版本如9.0.0该目录内既有dotnet宿主也有libcoreclr.so.dbg。拿到这样的环境后即可在 lldb 内执行clrstack等 SOS 命令查看崩溃时的托管调用栈。深入底层createdump 如何工作了解 dump 的来源有助于判断调试结果的可信度。核心库崩溃转储的生成机制记录在 xplat-minidump-generation.md 中其核心设计是当 coreclr 因为未捕获的托管异常或异步信号SIGSEGV、SIGILL、SIGFPE等即将调用PROCAbort()终止进程时会触发 dump 生成createdump工具位于libcoreclr.so同目录通过fork/execve启动为崩溃进程的子进程被赋予 ptrace 权限子进程用 ptrace 枚举并挂起目标进程的所有线程收集进程/线程状态与寄存器、auxv 条目、/proc/$pid/maps中的模块映射即 DSO 信息供 gdb/lldb 枚举共享模块和解析符号随后加载 DACData Access Component用于离线检查运行时托管状态的专用构建通过ICLRDataEnumMemoryRegions接口枚举托管状态所需的内存区域加入线程栈与 IP 周边一页代码把字节粒度区域按页取整并合并为连续区域最终按 ELF core 格式写出主 ELF 头、每个内存区域对应一个PT_LOADnote 条目、NT_FILE条目由/proc/$pid/maps构建、线程状态与寄存器以及各内存区域的实际内容。在仓库源码中这一流程体现在 createdumpunix.cpp 的CreateDump()里先crashInfo-EnumerateAndSuspendThreads()挂起线程再GatherCrashInfo()收集信息之后EnumerateMemoryRegionsWithDAC()借助 DAC 枚举托管内存最后dumpWriter.WriteDump()写出 ELF dump。命令行参数的解析则在 createdumpmain.cpp 的createdump_main()中完成。环境变量配置转储的生成由一组DOTNET_前缀的环境变量控制这些变量会在 PAL 层被读取见 process.cpp 中PROCAbortInitialize()对DbgEnableMiniDump、DbgMiniDumpName、DbgMiniDumpType等配置项的解析并作为选项传给createdump环境变量作用默认值DOTNET_DbgEnableMiniDump设为1时启用崩溃转储生成不生成 dumpDOTNET_DbgMiniDumpType转储类型见下表2MiniDumpWithPrivateReadWriteMemoryDOTNET_DbgMiniDumpNamedump 路径与文件名模板支持格式化占位符/tmp/coredump.%pDOTNET_DbgCreateDumpToolPath仅 NativeAOT自定义 createdump 工具所在目录无DOTNET_CreateDumpDiagnostics设为1启用 createdump 的诊断消息TRACE无DOTNET_CreateDumpVerboseDiagnostics设为1启用 verbose 诊断消息TRACE_VERBOSE无DOTNET_CreateDumpLogToFile诊断消息写入的文件路径无DOTNET_EnableCrashReport设为1且开启 MiniDump 时额外生成 JSON 格式崩溃报告dump 路径追加.crashreport.json无DOTNET_EnableCrashReportOnly同EnableCrashReport但不生成 core dump仅输出崩溃报告无注意在 Docker 容器内生成 core dump 需要为容器授予 ptrace 能力--cap-addSYS_PTRACE或使用--privileged。DOTNET_DbgMiniDumpType的取值与 Windows minidump 枚举对应值Minidump 枚举描述1MiniDumpNormal仅包含捕获进程所有线程栈回溯所需的信息GC 堆内存与信息受限2MiniDumpWithPrivateReadWriteMemory默认包含 GC 堆以及捕获所有线程栈回溯所需的信息3MiniDumpFilterTriage仅包含捕获所有线程栈回溯所需信息GC 堆内存受限4MiniDumpWithFullMemory包含进程全部可访问内存文件可能非常大在源码中这四类分别映射到 createdumpmain.cpp 的GetMiniDumpType()其中Heap默认还会叠加MiniDumpWithDataSegs、MiniDumpWithHandleData、MiniDumpWithThreadInfo等标志位。命令行参数createdump通常由运行时作为崩溃进程的子进程自动启动不能指定目标 PID它只转储其父进程。其命令行选项与上文-f/-h等开关一一对应解析逻辑见 createdumpmain.cppcreatedump [options] -f, --name 路径 - dump 路径与文件名默认 /tmp/coredump.%p支持 %p/%e/%h/%t 占位符 -n, --normal - 创建 minidump -h, --withheap - 创建带堆的 minidump默认 -t, --triage - 创建 triage minidump -u, --full - 创建完整 core dump -d, --diag - 启用诊断消息 -v, --verbose - 启用 verbose 诊断消息 -l, --logtofile - 诊断日志文件路径 --crashreport - 额外写崩溃报告dump 路径 .crashreport.json --crashreportonly - 仅写崩溃报告不生成 dump --crashthread id - 崩溃线程 id --signal code - 崩溃信号码 --singlefile - 单文件应用模型 --nativeaot - NativeAOT 应用模型dump 文件名模板支持的格式化占位符与 Linux core(5) 模式的子集一致占位符含义%%字面%字符%d/%p被转储进程的 PID%e进程可执行文件名%hgethostname()返回的主机名%tdump 时间自 Unix 纪元1970-01-01 UTC起的秒数常用调试流程总结综合原文档与仓库实现一次典型的 Unix 核心库崩溃调试流程为复现与收集在复现崩溃前设置DOTNET_DbgEnableMiniDump1必要时调整DOTNET_DbgMiniDumpType与DOTNET_DbgMiniDumpName运行测试复现得到/tmp/coredump.pid及配套的.crashreport.json若开启准备工具链确认 lldb 与 SOS 已安装并用 msbuild/t:Test至少成功运行过一次被测测试确保符号文件libcoreclr.so.dbg与程序集产物齐备加载转储按上文格式执行lldb -O settings set target.exec-search-paths runtime-path --core core-file host-path分析先用 lldb 原生命令确认符号已解析bt再用 SOS 命令clrstack、clrthreads、pe等分析托管层调用栈与对象状态对照源码结合 createdump 源码 与 转储生成设计文档 理解 dump 内容的覆盖范围判断分析结论的完备性。关于 SOS 命令集的更多用法如dumpheap、gcroot、soshelp可参考仓库内 debugging-corelib.md 等调试文档以及 diagnostics 仓库的 core dump 调试文档。【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址: https://gitcode.com/GitHub_Trending/runtime6/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →