GDB---coredump分析

本文介绍了如何在Linux环境下设置并生成coredump文件,以及如何利用gdb进行无-g编译版本的程序崩溃调试。包括coredump文件的配置、调试流程、使用gdb加载core文件定位问题等关键步骤,特别强调了通过编译选项-Wall、设置core_pattern参数等方法来辅助问题定位。

==============coredump文件产生设置=====release版本coredump的调试===============================================================
无-g编译的coredump以后怎么定位问题。以前都是用debug版本调试,然后出现问题也好定位,没关注过release版本怎么定位问题。今天就记录下怎么调试coredump。
调试方法
最好是把GCC编译选项-Wall打开,让所有编译警告都显示出来,并认真解决警告,有时候不处理警告会导致大问题;使用-g编译debug版本调试;设置系统能生成coredump文件。
1.core dump设置方式
(1)设置生成core dump文件
默认是不会产生core dump文件的,通过ulimit -c来查看core dump文件的大小,一般开始是0,设置ulimit -c unlimited后就能产生core dump文件。
(2)设置core dump文件名称
默认情况下,linux程序崩溃后会在可执行程序的目录下生成文件名称为core的文件,当然可以设置每次崩溃后的core dump文件名称为core+可执行文件名+pid这样的名称以便保留之前的core dump文件。
echo 'core.%e.%p' > /proc/sys/kernel/core_pattern
可以在core_pattern模板中使用变量还很多,见下面的列表:
%% 单个%字符
%p 所dump进程的进程ID
%u 所dump进程的实际用户ID
%g 所dump进程的实际组ID
%s 导致本次core dump的信号
%t core dump的时间 (由1970年1月1日计起的秒数)
%h 主机名
%e 程序文件名
2.如何调试coredump文件定位问题
(1)有-g编译的debug程序core dump后
test_debug为debug版本可执行程序
core.test_debug.30234为debug版本core dump文件
当程序core dump后用gdb命令加载core文件调试:gdb test_debug core.test_debug.30234
bt
l
info thread
(2)无-g编译的release程序coredump后
test_release为release版本可执行程序
core.test_release.30254为release版本core dump文件
gdb命令:gdb test_debug core.test_release.30254
命令格式就是gdb debug的可执行程序 release的core文件。
(3)调试无-g编译的release程序,这题与core dump文件无关
步骤1.相同的代码编译debug版本test_debug和release版本test_release;
步骤2.objcopy --only-keep-debug test_debug projectsymbol.dbg #生成符号表;
步骤3.gdb -q --symbol=projectsymbol.dbg -exec=test_release#加载符号表;
步骤4.像调试debug一样可以调试release了(不过我觉得这是多此一举,既然这台机器可以编译跑debug,为啥还要弄release呢?呵呵)
==============引入库===============================================================
(gdb) info share
From        To          Syms Read   Shared Object Library
                        No          /lib/libncore.so
                        No          /lib/libicuuc.so
可以看到很多库的符号表都没有被读入,看来果然如此。
输入用set solib-search-path + 库的路径 指定所要读取的符号表动态库所在位置,结果会看到很多done之类的信息,说明加载成功,  
现在bt下就能看到堆栈的详细信息了。
(gdb) bt
#0  nutshell::SourceUSB_ScannerThread::setScannerState (this=0x0,
    state=nutshell::SourceUSB_ScannerThread::SCANNERSTATE_START)
    at system/MediaLibrary/SourceUSB/src/Thread_Scanner/SourceUSB_ScannerThread.cpp:138
#1  0x2ae1ce1a in nutshell::SourceUSB_Scanner_EventHandler::onHandle (this=0xaf4a0, cEvt=...)
============查看线程信息,frame信息,变量信息==========================================
看样子是个多线程的应用,用threads命令看看都有哪些线程,切换过去逐个再bt
(gdb) info threads
  21 process 5797  0x00000038e8d7186d in memset () from /lib64/tls/libc.so.6
  20 process 5839  0x00000038e8dc6c8c in epoll_wait () from /lib64/tls/libc.so.6
(gdb) thread 21
[Switching to thread 21 (process 5797)]#0  0x00000038e8d7186d in memset () from /lib64/tls/libc.so.6
(gdb) bt
#0  0x00000038e8d7186d in memset () from /lib64/tls/libc.so.6
(gdb) f 3
#3  0x000000000049cb2d in CGSPduFactory::derivePdu (
is=@0x7fff9b436360, ulPDULen=30506) at common/pdu/gspdu.cpp:79
使用命令 i locals,打印所有的变量的值。
(gdb) i locals
pPdu = (CBasePdu *) 0x2aaaec951650
pPduHeader = (CPduHeader *) 0x2aaaea1c4190
ulPduType = 50
到现在还没有看出有什么明显的异常,然后再把PDU的头打印出来如下:
(gdb) p *pPduHeader
$1 = {m_ulHeadLen = 61, m_ulVersion = 2080000, m_ulPduType = 50, m_ulSrcSvrType = WEBEX_CONNECT_GS, m_strSrcSvrAddr = {
(gdb) f 1
#1  0x000000000049da0d in CGSPduFactory::streamStringFrom (
is=@0x7fff9b436360, strFrom=@0x2aaaec979760) at common/pdu/gspdu.cpp:422
422                  in common/pdu/gspdu.cpp
(gdb) i locals
strTmp = 0x2aaaf1c00010 ""
iRet = 0
ulLen = 1179995975

转载于:https://www.cnblogs.com/xfei-zhang/p/5086859.html

<think>嗯,用户想用arm-none-eabi-gdb分析coredump文件,我得先回忆一下相关知识。首先,coredump是在程序崩溃时生成的内存转储文件,用来调试问题。但嵌入式环境下可能没有操作系统支持生成coredump,所以需要确认用户的环境是否配置了相关机制,比如使用ulimit设置或者特定的调试工具。 接下来,用户使用的工具是arm-none-eabi-gdb,这是针对嵌入式ARM架构的GDB版本。和常规的GDB不同,它可能需要特定的配置,比如指定目标设备、加载正确的符号表和内存映射。需要确保用户生成的coredump文件与当前的可执行文件和调试符号匹配,否则分析时会出现地址无法解析的问题。 然后,步骤大致是启动gdb,指定可执行文件,然后加载coredump。可能需要使用命令如`target core`或者直接通过命令行参数加载。但记得在交叉编译环境中,可能需要使用`--core`选项来指定coredump文件。例如:`arm-none-eabi-gdb -ex "target core coredump.bin" my_program.elf`。 另外,用户可能需要设置正确的内存布局,特别是如果程序运行在特定的内存地址上,比如Flash或RAM。这时候可能需要使用`mem`命令或者加载链接器脚本,确保GDB能正确解析内存地址。 分析coredump时,查看堆栈回溯(backtrace)是关键,使用`bt`命令。但嵌入式环境下的backtrace可能不如在完整操作系统上那么容易,因为没有完善的栈帧信息或者符号表。可能需要检查编译时是否启用了调试选项(如-g),并且优化级别是否影响了调试信息的准确性。 可能遇到的问题包括:无法识别coredump格式,这时候需要确认生成coredump的工具是否兼容GDB;内存地址错误,需要检查链接脚本和加载地址;缺少调试信息,需要确保可执行文件包含符号表。 还有,用户可能没有正确配置GDB的环境,比如使用--sysroot指定系统根目录,或者需要设置搜索路径来查找库文件。引用中的--sysroot选项和-isysroot可能会影响头文件和库的搜索路径,这在加载符号时很重要。 最后,建议用户生成coredump的方法,比如使用调试器触发保存内存快照,或者配置系统在崩溃时自动生成。如果用户的环境不支持生成coredump,可能需要其他方法,比如实时调试或日志记录。 需要确保提供的步骤详细且准确,特别是针对ARM嵌入式系统的特殊性。可能还需要提醒用户注意编译器优化对调试的影响,比如优化级别过高可能导致变量无法查看或堆栈跟踪不准确。</think>### 如何用 arm-none-eabi-gdb 分析 coredump 文件 #### 1. 准备工作 - **生成调试符号**:编译代码时需添加 `-g` 选项(如 `arm-none-eabi-gcc -g -o program.elf`),确保可执行文件包含完整的调试信息[^2]。 - **获取 coredump 文件**:需确保目标设备已配置生成 coredump 的机制(例如通过调试器手动触发内存转储,或使用 `ulimit -c unlimited` 类指令配置系统级支持)。 #### 2. 启动 GDB 加载核心转储 ```bash arm-none-eabi-gdb program.elf -c coredump.bin # 或分步执行: arm-none-eabi-gdb program.elf (gdb) core-file coredump.bin ``` 若遇到路径问题,需通过 `--sysroot=dir` 指定库和头文件的逻辑根目录[^2]。 #### 3. 关键调试操作 - **查看崩溃位置**: ```bash (gdb) bt # 显示完整的调用栈回溯 (gdb) frame N # 切换到特定栈帧(N 为帧编号) ``` 嵌入式环境下需确保栈帧信息未被编译器优化破坏,建议检查编译时的优化级别(如 `-O0` 禁用优化)[^3]。 - **分析寄存器与内存**: ```bash (gdb) info registers # 显示寄存器状态 (gdb) x/10x 0x20000000 # 查看内存地址内容(示例地址需替换为实际) ``` #### 4. 特殊场景处理 - **内存布局匹配**:若程序运行地址与链接脚本定义不符,需通过 `mem` 命令手动设置内存区域: ```bash (gdb) mem 0x08000000 0x0800FFFF ro # 设置 Flash 区域 (gdb) mem 0x20000000 0x2000FFFF rw # 设置 RAM 区域 ``` - **符号表加载**:若动态库未正确加载,需通过 `set solib-search-path` 指定库路径。 #### 5. 常见问题排查 - **"No symbol table" 错误**:检查可执行文件是否包含调试符号,或尝试重新编译。 - **地址无法解析**:确认内存转储与当前程序版本一致,或检查链接脚本中的内存分配是否冲突。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值