| name | coredump_diagnose |
| description | 面向 Linux 用户态 coredump(core 文件)的结构化诊断技能。适用于进程崩溃、SIGSEGV/SIGBUS/SIGABRT/SIGFPE、空指针、栈溢出、内存破坏、总线错误、除零、Python+C 混合栈等场景;当用户提到 core、coredump、gdb 分析崩溃、段错误、总线错误、生成 core、应用转储时应触发。依赖系统已安装 GNU gdb;报告日志默认写入 /tmp/core_diag/。 |
Coredump 诊断
目标
在最短路径内完成 core 可用性校验、全量信息采集与场景归类(含 SIGBUS 等与 SIGSEGV 不同的分支),并按场景下钻给出可验证的崩溃链与根因假设;输出统一的报告日志路径(绝对路径)便于归档与自动化。
技能目录结构
coredump_diagnose
├── scripts
│ ├── pre_check.sh
│ ├── collect_and_classify.sh
│ ├── analyze_nullptr.sh
│ ├── analyze_stack_overflow.sh
│ ├── analyze_memory_corrupt.sh
│ ├── analyze_sigbus.sh
│ ├── analyze_abort.sh
│ └── analyze_divzero.sh
└── SKILL.md
以下命令默认在技能根目录 coredump_diagnose 下执行(或把路径写成仓库内的绝对路径)。
总流程(四阶段)
- 第一阶段:前置环境检查与二进制发现(
pre_check.sh)
- 第二阶段:信息收集与场景指纹归类(
collect_and_classify.sh)
- 第三阶段:按场景深度下钻(
analyze_*.sh)
- 第四阶段:反思与交叉验证 → 输出根因分析结论
第一阶段:前置环境检查
检查内容
| 项 | 说明 |
|---|
| GDB 可用性 | 验证系统是否安装 gdb,无则无法继续 |
| Core 合法性 | coredump 是否存在、可读 |
| 二进制发现与校验 | 支持 --binary 手动指定;未指定时从 core 头信息尝试提取可执行路径,并校验存在、可读 |
| 调试符号 | 粗查是否含 -g 调试信息,无符号时提示行号可能缺失 |
脚本执行命令
bash ./scripts/pre_check.sh --core <coredump 文件路径> [--binary <崩溃程序绝对路径>]
产出
- 终端打印
CORE_PATH、BINARY_PATH(绝对路径,可直接复制给后续脚本)
- 自动发现的二进制路径会缓存在
/tmp/.coredump_auto_bin.tmp(供同一会话逻辑使用)
第二阶段:信息收集及分类
采集内容(写入报告日志)
- 程序与信号:终止原因、系统信号、崩溃地址
- 完整 C 层调用栈:栈帧关系、
bt full、局部变量与函数入参
- 寄存器:通用寄存器与 PC 现场
- 反汇编:崩溃指令前后汇编,辅助指令级定位
- 内存映射:堆、栈、共享库范围,用于判断地址是否合法
- 全线程:各线程状态与栈,排查并发问题
- Python 增强(可选):自动尝试
py-bt、py-locals(需 python3-dbg / python3-debuginfo 等,失败会降级提示)
脚本执行命令
bash ./scripts/collect_and_classify.sh \
--core "<前置检查输出的 CORE_PATH>" \
--binary "<前置检查输出的 BINARY_PATH>"
GDB 调用约定(与脚本实现一致)
collect_and_classify.sh 与各 analyze_*.sh 使用 gdb --quiet --batch -x <临时脚本>:命令写入临时文件,避免部分环境下 --batch 从 stdin 读命令不稳定;小节标题用 Python gdb.write。会话输出由 shell 重定向 写入报告日志(不在 GDB 内 set logging 与重定向混用)。
产出说明
| 产出 | 说明 |
|---|
| 报告日志 | /tmp/core_diag/collect_and_classify_<时间戳>.log(自动 mkdir -p /tmp/core_diag) |
| 摘要 | 场景分类与「下一步推荐命令」经 tee 追加到同一日志;终端打印摘要并输出 报告日志绝对路径:(realpath) |
场景指纹 → 归属(本步自动分类)
| 条件(基于 GDB 日志解析) | 场景 | 下一步脚本 |
|---|
SIGSEGV 且故障地址为 0x0 | 空指针 | analyze_nullptr.sh |
SIGSEGV 且栈深度 > 50 | 栈溢出 | analyze_stack_overflow.sh |
SIGSEGV 且非 0x0 的非法地址 | 内存破坏/野指针/越界 | analyze_memory_corrupt.sh |
SIGBUS(且未落入空指针/深栈分支) | 总线错误 | analyze_sigbus.sh |
SIGABRT | 主动终止/堆损坏/异常 | analyze_abort.sh |
SIGFPE | 算术异常(如除零) | analyze_divzero.sh |
SIGILL / SIGSYS / SIGXCPU / SIGXFSZ 等 | 少见信号(other) | 无专项;通读收集日志人工分析 |
| 其余未列信号 | unknown | 人工研判 |
路径提示:collect_and_classify.sh 内嵌的下一步示例可能为 ./skills/...;实际执行请统一使用 bash ./scripts/analyze_*.sh(在技能根目录下)或仓库内绝对路径。
第三阶段:按场景深度下钻
原则:先验证「现象与信号是否一致」,再解释「地址/栈为何指向该场景」,最后界定「需代码侧补证的部分」。
各 analyze_*.sh 的报告日志为 /tmp/core_diag/analyze_<场景>_<时间戳>.log,结束前终端打印 报告日志绝对路径:。
场景 1:空指针访问(analyze_nullptr.sh)
脚本执行命令
bash ./scripts/analyze_nullptr.sh \
--core "<CORE_PATH>" \
--binary "<BINARY_PATH>"
方法论
在崩溃栈顶帧(Frame 0)对齐源码与变量,确认触发访问的指针名及对应代码行。结合 disas 区分本次段错误是由读还是写访问触发,避免误判为「仅读」或「仅写」类问题。沿调用栈向上追踪该指针的来源,区分函数入参、未初始化局部变量、全局或静态对象被置空等路径。最后将 GDB 结论映射回源码,标出缺少非空校验或错误分支未覆盖的位置,作为修复与单测依据。
判定标准:SIGSEGV,且崩溃时访问地址为 0x0。
场景 2:栈溢出(analyze_stack_overflow.sh)
脚本执行命令
bash ./scripts/analyze_stack_overflow.sh \
--core "<CORE_PATH>" \
--binary "<BINARY_PATH>"
方法论
结合浅层与深层栈片段(如 bt 20 / bt -20)观察栈深度与是否存在同一符号反复出现的递归模式。在栈顶帧检查 info locals,识别过大的栈上数组或结构体导致栈帧耗尽。若为递归,重点审查终止条件与边界输入,解释为何未能正常退出。同时保留对栈越界写的怀疑:异常深的栈或损坏的返回地址可能与此相关,需对照源码与反汇编排除。
判定标准:SIGSEGV,且第一步分类中栈层数 > 50,或日志与源码共同指向超大栈上对象/深度递归。
场景 3:内存破坏 / 野指针 / 越界访问(analyze_memory_corrupt.sh)
脚本执行命令
bash ./scripts/analyze_memory_corrupt.sh \
--core "<CORE_PATH>" \
--binary "<BINARY_PATH>"
方法论
将崩溃地址与 info proc mappings 对照,判断其落在堆、栈、映射库还是未映射区,区分「合法区域内的非法访问」与「完全野地址」。在 x86_64 上结合 RDI/RSI/RDX 等参数寄存器及其指向内存的转储,判断数据是否像已释放、未初始化或垃圾值。用带机器码的反汇编锁定具体访存指令,推断非法地址是在本条指令形成还是更早被写坏。最后从时间顺序上优先怀疑崩溃前最近的写操作,排查越界、UAF、双重释放与未初始化指针等典型根因。
判定标准:SIGSEGV,且访问地址非 0x0,常见为随机值、已释放堆块附近或明显非法区间。
场景 4:程序主动终止(analyze_abort.sh)
脚本执行命令
bash ./scripts/analyze_abort.sh \
--core "<CORE_PATH>" \
--binary "<BINARY_PATH>"
方法论
从完整栈与多线程栈中区分三类典型路径:malloc/free 路径上的堆损坏(如 malloc_printerr、__libc_message)、C++ 异常路径(如 __cxa_throw、未捕获异常)以及显式 abort/断言失败。若为堆问题,集中审计近期分配释放配对、越界写堆块元数据、double free 等。若为 C++ 异常,尽量定位异常类型与抛出栈,并检查是否缺少 catch 或在析构中二次抛掷。结合业务逻辑确认 abort() 或断言的触发条件是否与配置、输入或资源失败一致。
判定标准:SIGABRT,且栈上常出现 __GI_abort、__libc_message、__cxa_throw 等特征符号(以实际日志为准)。
场景 5:算术错误 / 除零(analyze_divzero.sh)
脚本执行命令
bash ./scripts/analyze_divzero.sh \
--core "<CORE_PATH>" \
--binary "<BINARY_PATH>"
方法论
在崩溃点附近反汇编中定位 div/idiv 及与之相关的数据移动,确认哪个寄存器或内存槽位作为除数。对照 info registers 与 info locals,核实除数是否为 0,并区分整型除零与取模 % 触发的 SIGFPE。沿数据流向上追问 0 的来源,区分计算溢出、默认值未改写、外部参数未校验等。修复上除崩溃点旁加判断外,更建议在数据入口或不变量处保证除数非零,并补充回归用例覆盖边界。
判定标准:SIGFPE,且崩溃点对应除法或取模,除数为 0。
场景 6:总线错误(analyze_sigbus.sh)
脚本执行命令
bash ./scripts/analyze_sigbus.sh \
--core "<CORE_PATH>" \
--binary "<BINARY_PATH>"
方法论
SIGBUS 与 SIGSEGV 的区分要点:总线错误往往是 CPU/内核对本次访存请求的拒绝(对齐、映射后端失效等),不仅限于「页内合法但权限错」这类典型段错误语义。生产环境中常见两类:一是 ARM 等架构下的未对齐访问;二是 mmap 映射文件被截断、删除或磁盘空间耗尽 导致映射区访问失效。排查时应 先确认运行架构与对齐约束,再对照 info proc mappings 将崩溃地址与 文件映射(含 MAP_SHARED)、匿名映射关联,并回溯业务侧 大文件 IO / mmap 路径。在排除对齐与映射类问题后,再考虑 物理内存异常、内核/驱动 等更底层原因。
判定标准:SIGBUS(第一步分类为 sigbus),且日志与反汇编、映射共同指向 对齐或映射/文件后端 相关问题(以实际采集为准)。
第三阶段产出要求
- 每个子场景日志内应具备:栈证据、寄存器/反汇编证据、与场景判定的一致性说明
- 明确列出需对照源码的待证命题(例如「某指针在何分支被置空」)
第四阶段:反思与交叉验证
目标:避免「单条栈或单次信号」定根因,确保结论可反驳、可补证。
4.1 反思方法论
- 区分 症状(信号、崩溃地址)、机制(哪条指令、哪段内存)、根因(代码路径、生命周期、并发假设);勿将症状直接写成根因。
- 质疑当前主场景:例如「看似野指针是否实为截断后的空指针」「
SIGABRT 是否为 OOM/abort 钩子而非堆损坏」。
- 证据不足时显式保留不确定性,列出「待补证据」(符号包、复现条件、同版本二进制)。
4.2 交叉验证方法论
- 信号 ↔ 栈:
SIGSEGV 的地址与 maps 是否一致;SIGBUS 是否与未对齐、文件映射截断/mmap 路径一致;SIGABRT 是否真来自断言/堆检查。
- 多线程:
thread apply all bt 是否与单线程假设矛盾。
- 构建信息:无调试符号时,结论置信度降级,并建议
-g 重编或安装 debuginfo。
- 独立源:若仅有 GDB 输出,建议补充同一崩溃点的应用日志、系统日志(时间对齐)。
第五阶段:输出根因分析结论
按以下模板输出最终结论;缺失项标注 待补证据。
## 用户态 Coredump 根因分析结论
### 1) 基本信息
- 崩溃进程:<名称 / PID 若可知>
- Core 文件:<路径>
- 分析二进制:<路径>(是否与 core 匹配:是/否/待核实)
- 报告日志:<collect / analyze 的 /tmp/core_diag/*.log 绝对路径>
### 2) 崩溃事件链(Crash Chain,按时间/因果而非诊断步骤)
- C0:<加载/启动/输入 若可知>
- C1:<首次异常条件,如空指针解引用、除数为 0>
- C2:<信号与现场,如 SIGSEGV @0x0>
- C3:<若涉及库/线程,扩大影响或二次失败>
### 3) 根因链(Causal Chain)
- 直接原因:<例如对空指针解引用>
- 中间机制:<例如未校验返回值即解引用>
- 深层原因:<例如错误分支未覆盖、并发下对象已释放>
- 触发条件:<输入/配置/竞态/特定构建>
### 4) 证据清单(支持 / 反证)
- 支持证据:
- <GDB 日志片段:信号、Frame 0、地址>
- <反汇编或寄存器与结论一致处>
- 反证与排除:
- <已排除场景 + 理由,如非栈溢出因栈深度正常>
### 5) 结论置信度
- 置信等级:<高/中/低>
- 置信依据:<符号是否齐全、是否可复现、是否多源一致>
### 6) 修复与预防
- 即时修复:<代码/配置层建议>
- 长期治理:<静态检查、Review 点、测试用例、监控探针>
- 验证方式:<复现步骤关闭后应观察到何现象>
约束与提示
- 本技能针对 用户态 core + GNU gdb;内核 vmcore 请使用专用 crash/vmcore 流程。
- 无
--output:所有报告均落在 /tmp/core_diag/,文件名含脚本名与时间戳;以终端打印的 realpath 为准归档。
- 各分析脚本已统一为
-x 临时脚本;若某环境仍有异常,检查 GDB 版本 与 core/可执行文件路径是否匹配。