制造可控故障,生成 Core Dump,并用匹配的程序和符号定位问题

发布时间:2026/11/5 5:32:56

制造可控故障,生成 Core Dump,并用匹配的程序和符号定位问题 制造可控故障生成 Core Dump并用匹配的程序和符号定位问题前几篇已经在 QEMU ARM64 中运行了交叉编译的程序并使用 Dropbear 完成了密钥登录和 SSH 端口转发。本篇继续练习故障定位在 guest 中运行一个会主动触发SIGABRT的小程序生成 core dump再把 core 文件取回 Ubuntu使用与崩溃程序完全匹配的 ARM64 可执行文件和调试符号查看调用栈、参数及局部变量。本文的故障是专门设计的可控崩溃不修改现有debug_demo服务也不模拟真实设备故障。Core dump 可能包含崩溃进程的内存数据实验文件只用于本机练习不应公开或提交到版本库。一、实验流程与环境实验流程如下Ubuntu 20.04 x86_64 主机离线分析QEMU ARM64 guest故障注入与 core 生成Ubuntu 20.04 x86_64 主机编译与准备SSH 上传经 127.0.0.1:2222 和 QEMU hostfwdSSH 取回core_dump_demo.cBuildroot AArch64 GCC-O0 -g3 -gdwarf-4未剥离 ARM64 ELFBuild ID DWARFDropbear TCP 22公钥登录/root/core_dump_demoulimit -c unlimitedcore_pattern 指向 /root运行测试程序触发 SIGABRT/root/core.core_dump_demo.PID取回的 core 文件Buildroot 交叉 GDBsysroot: output/stagingSIGABRT、调用栈、参数和源码行项目本文沿用的设置Ubuntu 主机Ubuntu 20.04 x86_64Buildroot2025.02.8~/buildroot-2025.02.8Buildroot 输出目录~/buildroot-output-arm64-demo外部树~/buildroot-external-demo目标系统QEMU ARM64BusyBox init可写 ext2 rootfsguest SSH前文配置的 DropbearUbuntu127.0.0.1:2222转发到 guest TCP 22测试程序core_dump_demo由当前 Buildroot 工具链编译本文假设 QEMU guest 已启动、Dropbear 公钥登录可用且$HOME/.ssh/buildroot-qemu-dropbear-ed25519可用于 SSH。本文会在 QEMU guest 的/root下运行程序并生成 core不要在 Windows PowerShell、Ubuntu 主机或其他生产设备上执行故障注入命令。二、准备交叉编译器和 GDB以下命令在Ubuntu 主机执行。设置沿用前文的输出目录并查找 Buildroot 交叉编译器exportDEMO_OUT$HOME/buildroot-output-arm64-demoexportDEMO_EXT$HOME/buildroot-external-demoexportSSH_KEY$HOME/.ssh/buildroot-qemu-dropbear-ed25519exportCORE_WORK$HOME/core-dump-demomkdir-p$CORE_WORKexportCROSS_GCC$(find$DEMO_OUT/host/bin-maxdepth1\-nameaarch64-buildroot-linux-*-gcc-print-quit)if[-z$CROSS_GCC];thenprintfBuildroot AArch64 compiler not found under %s/host/bin\n$DEMO_OUT2elseexportCROSS_PREFIX${CROSS_GCC%-gcc}exportCROSS_GDB${CROSS_PREFIX}-gdbexportCROSS_READELF${CROSS_PREFIX}-readelfprintfCompiler: %s\nGDB: %s\nReadelf: %s\n\$CROSS_GCC$CROSS_GDB$CROSS_READELFif[!-x$CROSS_GCC];thenprintfBuildroot AArch64 compiler is not executable\n2elif[!-x$CROSS_READELF];thenprintfMatching readelf not found: %s\n$CROSS_READELF2elif[-x$CROSS_GDB];thenechoBuildroot AArch64 GDB is available.elseechoBuildroot AArch64 GDB is missing; build host-gdb as described below.fifi上述变量从编译器路径推导出同一工具链前缀。若未找到编译器、它不可执行或readelf缺失请先修复对应路径/工具后再继续若只缺少 GDB按下文启用并构建host-gdb。检查失败只显示提示不会用exit关闭当前终端。上述export只对当前终端有效若另开 Ubuntu 终端执行后续命令请重新执行本节的变量设置。本轮 Ubuntu 主机检查通过交叉编译器、readelf和 GDB 均可用用户名路径以$HOME简写Compiler: $HOME/buildroot-output-arm64-demo/host/bin/aarch64-buildroot-linux-gnu-gcc GDB: $HOME/buildroot-output-arm64-demo/host/bin/aarch64-buildroot-linux-gnu-gdb Readelf: $HOME/buildroot-output-arm64-demo/host/bin/aarch64-buildroot-linux-gnu-readelf Buildroot AArch64 GDB is available.GDB 必须是运行在 Ubuntu 主机上的 AArch64 交叉 GDB不是 guest 里的gdbserver。如果找不到交叉 GDB可参照前一篇 GDB 远程调试教程在 Buildroot 中启用BR2_PACKAGE_HOST_GDB并构建host-gdb。不要仅凭 Ubuntu 自带 GDB 版本较新就假定它能读取当前目标产生的 core以实际加载结果为准。三、创建带调试符号的可控故障程序在Ubuntu 主机创建测试程序cat$CORE_WORK/core_dump_demo.cEOF #include stdio.h #include stdlib.h __attribute__((noinline)) static void crash_point(int request_id, int value) { int computed_value value * 2; fprintf(stderr, controlled crash: request_id%d computed_value%d\n, request_id, computed_value); abort(); } __attribute__((noinline)) static void process_record(int request_id, int payload) { int scaled_value payload * 3; crash_point(request_id, scaled_value); } int main(void) { process_record(42, 7); return 0; } EOF找到的编译器路径填入CROSS_GCC用-O0保留直观的变量和源码行信息并生成 DWARF 调试信息与 ELF Build ID$CROSS_GCC\-Wall-Wextra-O0-g3-gdwarf-4 -fno-omit-frame-pointer\-Wl,--build-idsha1\$CORE_WORK/core_dump_demo.c\-o$CORE_WORK/core_dump_demofile$CORE_WORK/core_dump_demo若真实编译器路径不同应先更新CROSS_GCC不要继续使用不存在的示例路径。file应显示 ARM AArch64 ELF并包含debug_info、not stripped等信息。后续 GDB 必须加载这个同一次编译产生的未剥离程序重新编译或替换程序后旧 core 不一定还能与新符号对应。本轮 Ubuntu 主机实际输出如下用户名路径以$HOME简写$ file $CORE_WORK/core_dump_demo $HOME/core-dump-demo/core_dump_demo: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]f85d2d19952a5b058538905875382b8a68feb391, for GNU/Linux 6.12.0, with debug_info, not stripped这确认交叉编译成功产物是带调试信息且未剥离的 AArch64 ELF后续应继续用这个文件部署并分析对应 core。检查 Build ID$CROSS_READELF-n$CORE_WORK/core_dump_demo|grepBuild ID本轮 Ubuntu 主机实际输出如下Build ID: f85d2d19952a5b058538905875382b8a68feb391该值与前面file显示的 Build ID 一致。后续保存程序与 core 时不要混用其他构建目录中的同名文件。四、把相同程序放入 QEMU guest使用前文已配置的 Dropbear SSH从Ubuntu 主机把刚编译的二进制通过标准输入传到 guest。这样传入 guest 的就是后续在主机上提供给 GDB 的同一份 ELF不需要重建 rootfsssh-i$SSH_KEY-p2222root127.0.0.1\cat /root/core_dump_demo chmod 755 /root/core_dump_demo\$CORE_WORK/core_dump_demo如 SSH 首次提示 host key按前文流程先核对指纹输入私钥口令时终端不会回显字符。传输命令返回且没有错误后可继续在Ubuntu 主机终端通过 SSH 确认 guest 中的文件不要在 Ubuntu 主机直接执行ls /root/core_dump_demo那会检查主机自己的/rootssh-i$SSH_KEY-p2222root127.0.0.1\ls -l /root/core_dump_demo test -x /root/core_dump_demo echo executable本轮 Ubuntu 主机通过 SSH 检查 guest 的实际输出如下-rwxr-xr-x 1 root root 47384 Nov 2 11:34 /root/core_dump_demo executable输出确认测试程序已传入 QEMU guest且具有执行权限。不要在传输后重新编译 guest 上的程序。若必须重新编译应将新的 ELF 同时用于 guest 运行和 Ubuntu 上的 GDB并重新生成新的 core。五、在 guest 中启用 core dump 并触发故障以下命令全部在QEMU 目标端执行。先确认/root有足够空间然后在当前 shell 中设置 core 文件大小限制并设置明确的保存路径df-h/rootulimit-cunlimitedulimit-cprintf/root/core.%%e.%%p\n/proc/sys/kernel/core_patterncat/proc/sys/kernel/core_patternulimit -c unlimited只影响当前 shell 及之后启动的子进程因此要在这个 shell 中直接启动测试程序。core_pattern是 guest 内核的全局设置本例将文件写入可写 rootfs 的/root名称格式为core.进程名.PID。不要把此设置误写到 Ubuntu 主机的/proc。本轮 QEMU guest 的实际配置输出如下# df -h /root Filesystem Size Used Available Use% Mounted on /dev/root 51.1M 7.6M 39.3M 16% / # ulimit -c unlimited # ulimit -c unlimited # printf /root/core.%%e.%%p\n /proc/sys/kernel/core_pattern # cat /proc/sys/kernel/core_pattern /root/core.%e.%p这确认当前 shell 允许生成不受大小限制的 coreguest 内核也会将 core 写入/root。当前根文件系统报告约39.3M可用空间生成后仍需检查 core 是否完整写入。触发可控故障cd/root ./core_dump_demo程序调用abort()预期以SIGABRT终止BusyBox shell 可能显示Aborted (core dumped)。随后确认 core 文件存在ls-lh/root/core.core_dump_demo.*本轮 QEMU guest 的实际崩溃输出如下# cd /root # ./core_dump_demo controlled crash: request_id42 computed_value42 Aborted (core dumped)程序按预期因SIGABRT退出。接下来必须用ls确认 core 文件确实存在并记录其大小PID 和文件大小以现场输出为准。若没有 core 文件不要继续 GDB 分析先按第九节检查限制值、core_pattern、可写空间和内核支持。本轮 QEMU guest 的 core 文件检查结果如下# ls -lh /root/core.core_dump_demo.* -rw------- 1 root root 264.0K Nov 2 11:37 /root/core.core_dump_demo.137core 文件已生成大小为264.0Kguest PID 为137。六、将 core 文件取回 Ubuntu在Ubuntu 主机的新终端执行以下命令从 guest 取回本轮生成的 core。该终端需重新设置 SSH key 和工作目录变量CORE_NAME使用上一节现场确认的文件名exportSSH_KEY$HOME/.ssh/buildroot-qemu-dropbear-ed25519exportCORE_WORK$HOME/core-dump-demoexportCORE_NAMEcore.core_dump_demo.137if[-e$CORE_WORK/$CORE_NAME];thenprintfDestination already exists; choose another CORE_NAME.\n2elseCORE_TMP$(mktemp$CORE_WORK/.core-transfer.XXXXXX)if[-n$CORE_TMP];thenif(umask 077;ssh-i$SSH_KEY-p2222root127.0.0.1\cat /root/$CORE_NAME\$CORE_TMP);thenif[-s$CORE_TMP];thenchmod600$CORE_TMPmv$CORE_TMP$CORE_WORK/$CORE_NAME\ls-lh$CORE_WORK/$CORE_NAMEfile$CORE_WORK/$CORE_NAMEelseprintfCore transfer produced an empty file; do not analyze it.\n2rm-f$CORE_TMPfielseprintfSSH core transfer failed; do not analyze the output file.\n2rm-f$CORE_TMPfielseprintfCould not create a temporary core file under %s\n$CORE_WORK2fifi若 SSH 命令失败或文件为空检查 guest 上源 core 是否存在、Dropbear 连接和主机磁盘空间不要分析未成功取回的文件也不要把 core 上传到公共服务或直接附在问题报告中。本轮 Ubuntu 主机检查确认 core 文件大小为264Kfile的实际输出如下$CORE_WORK/core.core_dump_demo.137: ELF 64-bit LSB core file, ARM aarch64, version 1 (SYSV), SVR4-style, from ./core_dump_demo, real uid: 0, effective uid: 0, real gid: 0, effective gid: 0, execfn: ./core_dump_demo, platform: aarch64file确认该文件是 AArch64 core。core 可能包含敏感内存数据因此上述单次取回流程先设置umask 077复制后再将权限设为600。七、使用匹配的程序和符号分析在Ubuntu 主机启动 Buildroot 交叉 GDB参数依次是未剥离的 ARM64 程序和从 guest 取回的 coreexportDEMO_OUT$HOME/buildroot-output-arm64-demoexportCORE_WORK$HOME/core-dump-demoexportCORE_NAMEcore.core_dump_demo.137exportCROSS_GCC$(find$DEMO_OUT/host/bin-maxdepth1\-nameaarch64-buildroot-linux-*-gcc-print-quit)if[-n$CROSS_GCC];thenexportCROSS_GDB${CROSS_GCC%-gcc}-gdbexportCROSS_READELF${CROSS_GCC%-gcc}-readelfif[-x$CROSS_GDB];then$CROSS_GDB$CORE_WORK/core_dump_demo$CORE_WORK/$CORE_NAMEelseprintfBuildroot AArch64 GDB not found: %s\n$CROSS_GDB2fielseprintfBuildroot AArch64 compiler not found under %s/host/bin\n$DEMO_OUT2fi在(gdb)提示符逐条执行set pagination off set sysroot /home/Ubuntu用户名/buildroot-output-arm64-demo/staging sharedlibrary bt将/home/Ubuntu用户名/buildroot-output-arm64-demo/staging替换为当前 Buildroot 输出目录下的staging绝对路径。此交互顺序与本轮实际验证一致可让 GDB 找到 guest 匹配的 C 库和栈展开信息缺少 sysroot 时调用栈可能停在??或报告栈损坏。info program对 core 文件可能显示进程未在运行这不代表 core 加载失败以bt能否展开应用栈帧为准。本轮 GDB 设置 sysroot 并加载共享库后的实际 backtrace 如下。为避免暴露 Ubuntu 用户名输出中的绝对路径以$DEMO_OUT和$CORE_WORK简写#0 0x0000ffffbf277b20 in __pthread_kill_implementation () from $DEMO_OUT/staging/lib64/libc.so.6 #1 0x0000ffffbf2324dc in raise () from $DEMO_OUT/staging/lib64/libc.so.6 #2 0x0000ffffbf21e8c8 in abort () from $DEMO_OUT/staging/lib64/libc.so.6 #3 0x0000aaaacfefa818 in crash_point (request_id42, value21) at $CORE_WORK/core_dump_demo.c:12 #4 0x0000aaaacfefa848 in process_record (request_id42, payload7) at $CORE_WORK/core_dump_demo.c:20 #5 0x0000aaaacfefa868 in main () at $CORE_WORK/core_dump_demo.c:25调用栈从abort()完整展开到crash_point、process_record和main参数值也与测试程序的计算过程一致。从bt输出中找到crash_point对应的帧号再选中它并查看参数、局部变量和源码frame crash_point 的帧号 info args info locals list本轮在crash_point帧中的实际输出如下用户名路径以$CORE_WORK简写(gdb) frame 3 #3 0x0000aaaacfefa818 in crash_point (request_id42, value21) at $CORE_WORK/core_dump_demo.c:12 12 abort(); (gdb) info args request_id 42 value 21 (gdb) info locals computed_value 42 (gdb) list 7 int computed_value value * 2; 8 9 fprintf(stderr, 10 controlled crash: request_id%d computed_value%d\n, 11 request_id, computed_value); 12 abort(); 13 } 14 15 __attribute__((noinline)) 16 static void process_record(int request_id, int payload)实测确认request_id42、value21、computed_value42源码位置为abort()调用行。帧号不要照抄示例必须以当前bt输出为准。为什么必须匹配Core 记录崩溃进程的寄存器、内存映射和部分内存状态但不会替代原程序的调试符号。GDB 需要正确的 ARM64 ELF 来解释地址、函数名、行号及变量。若同名程序来自不同构建符号可能错误地映射到不相干的代码。本实验通过同一个$CORE_WORK/core_dump_demo文件直接传给 guest 并在主机侧用它分析保持二者一致。若之后重新编译、strip 或替换文件要重新部署程序、重新触发崩溃并保存对应 core。可用以下命令查看候选程序的 Build ID并与记录的构建产物核对$CROSS_READELF-n$CORE_WORK/core_dump_demo|grepBuild ID不要只根据文件名、时间戳或相同源码判断二进制匹配。八、常见问题现象优先检查程序显示Aborted但没有 core 文件当前 shell 的ulimit -c是否为unlimitedcore_pattern是否指向可写路径/root是否有空间检查内核 core dump 支持core_pattern以 开头core 文件名和预期不同查看/proc/sys/kernel/core_pattern%e是进程名%p是 guest PIDGDB 报not in executable format或架构不匹配使用 Buildroot 的 AArch64 交叉 GDB并检查file输出确认程序和 core 均属于 AArch64GDB 只显示地址或??确认加载的是未剥离且与崩溃程序同次构建的 ELF系统库符号缺失时应用自己的符号仍可单独检查变量显示不可用检查是否使用匹配的-O0 -g3ELF崩溃位置和变量生命周期也会影响可见性core 文件非常大或磁盘不足core 包含进程地址空间内容确认 guest 可用空间只在实验后保留所需文件并安全清理SSH 取回 core 失败确认 QEMUhostfwd、Dropbear 和公钥登录仍可用并使用 guest 中实际 core 文件名九、实验边界与安全注意事项本篇演示的是 Linux 用户态进程在 QEMU ARM64 中生成 core并在 Ubuntu 主机使用匹配的程序和符号离线分析。它不覆盖内核崩溃、JTAG、真实板卡外设、生产服务的自动 core 收集或 systemd-coredump。Core 文件可能包含进程内存中的口令、令牌、密钥、用户数据和网络内容。示例用 root 在 guest/root下生成 core 只是为了简化权限和传输不要把 core、私钥或未经脱敏的调试输出提交到代码仓库或公开发布。实验结束后在 QEMU guest 和 Ubuntu 主机分别删除本次专用程序与 core 文件确认不会误删其他实验文件。十、小结通过在 Buildroot 交叉编译一个带调试信息的 ARM64 程序、在 QEMU guest 设置 core dump 限制并触发可控SIGABRT可以得到用户态 core 文件。将 core 取回 Ubuntu 后使用同一次构建产生的未剥离 ELF 和 AArch64 交叉 GDB即可从崩溃现场检查信号、调用栈及应用变量。可靠分析的关键不是文件名相同而是 core、运行程序和调试符号确实对应同一构建。参考资料Linuxcore(5)手册Linuxgetrlimit(2)手册GDBCore File GenerationGDBFilesBuildroot 官方手册
延伸阅读

更多相关文章

2026/11/5 5:27:56

FDE如何从一个陌生行业中,找到10个值得落地的AI场景?

从行业研究、业务流程拆解到场景评估,一套可复用的企业AI机会发现方法论 作者|FDE前线 当AI Agent、RAG、工作流自动化等技术逐渐成熟,企业AI落地的一个重要问题正在发生变化:技术人员已经能够较快地搭建应用原型,但…

2026/11/5 6:23:01

在线表格组件选型指南:从Excel导入到协作编辑的工程实践

从一个在线表格需求说起如果你在团队里待过,大概率遇到过这类需求:"做个页面,把Excel传上来,能看能编辑,最好还能多人同时改。"第一次听到这种需求的人,通常觉得不难——放个表格组件不就行了吗&…

2026/11/5 6:23:01

智能弹窗处理技术在自动化测试中的应用与实践

1. 项目背景与核心价值墨迹天气作为国内头部天气服务应用,其App在功能迭代过程中面临着复杂的测试挑战。特别是在自动化测试场景下,各类系统弹窗、权限请求弹窗、活动推广弹窗成为测试脚本稳定性的主要威胁。传统录制回放式自动化测试在面对这类非预期弹…

2026/11/5 6:23:01

贝叶斯模型:从原理到实践的核心指南

1. 贝叶斯模型的核心直觉贝叶斯模型最迷人的地方在于它完美模拟了人类认知世界的方式——我们总是基于已有经验(先验)来理解新信息(似然),然后不断修正自己的认知(后验)。举个生活中的例子&…

2026/11/5 6:23:01

MaxKB开源企业级智能体平台架构与应用实践

1. 项目背景与里程碑意义MaxKB作为一款开源企业级智能体平台,近期迎来了一个重要里程碑——全网累计下载量突破100万次。这个数字不仅代表了技术社区对产品的认可,更反映了当前企业智能化转型的迫切需求。作为一个长期关注AI落地的从业者,我见…

2026/11/5 6:23:01

Univer开源在线表格实战:高性能渲染、公式计算与协同编辑全解析

近几年接手的项目里,只要需求文档里出现“在线表格”四个字,我第一反应永远是先深吸一口气。原因很简单:看似只是“把 Excel 搬进浏览器”,实际牵扯到渲染性能、公式计算、格式兼容、协同编辑、权限控制一堆问题。Univer 是我在反…

2026/11/5 6:18:01

Archery开源SQL审核平台Docker部署指南

1. Archery项目简介与部署概述Archery是一款开源的SQL审核平台,由国内技术团队开发维护,主要用于企业级数据库管理、SQL审核和慢查询分析。作为一款基于Docker容器化部署的应用,它整合了MySQL、Redis、Inception等组件,为DBA和运维…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑