gdb调试core dump 文件

1 空指针core dump文件分析

把core文件从开发板拷贝到本地主机,用gdb命令打开,命令格式为:

aarch64-unknown-nto-qnx7.1.0-gdb executable-file core-file

打开一个因为空指针问题导致的coredump文件:

可以发现是SIGSEGV信号导致的:

出错地址为:

在 gdb中输入 info sharedlibrary:

可以发现0x0000000078cf3ff8 这个出错地址比程序加载的动态库libqcx_max96722_avm.so的起始地址大,因为这边没有加载libqcx_max96722_avm.so 库到gdb中,所以gdb只知道该库加载的起始地址,不知道该库的大小。可以使用readelf 工具,来查看该动态库在内存中的镜像有多大,利用 readelf -l 命令,查看动态库的program header:

第一列type指的是该动态库的属性,LOAD 属性说明该部分运行的时候会加载进系统RAM 中。该共享库在RAM中的大小即为0x0000000000008d40+0x0000000000011c50=1A990,

所以libqcx_max96722_avm.so在RAM中的结束地址为0x0000000078cf2000+1A990=78d0c990, 所以程序的出错地址就在libqcx_max96722_avm.so程序中。

利用objdump命令,对libqcx_max96722_avm.so 动态库进行反汇编:

aarch64-unknown-nto-qnx7.1.0-objdump -S libqcx_max96722_avm.so

反汇编生成的文件汇编地址是从0开始的,而出错地址和反汇编地址之间,会有一个offset, 出错地址在libqcx_max96722_avm.so反汇编文件中的地址需要减去该动态库在RAM中的起始地址

0x0000000078cf3ff8 - 0x0000000078cf2000=1ff8,出错地址在反汇编文件中为1ff8:

1ff8中的汇编代码的意思是把0写入x0寄存器指向的地址中,用info reg看一下x0寄存器值:

向地址为0的内存写入了0,所以是空指针操作导致了coredump。

观察汇编发现该x0的值就是detect_null_pointer的参数,而detect_null_pointer 又由MAX96722_AVMIoctl调用:

在0x20a8的位置,从 sp+88的地址处取出值,传给x0,而 sp+88地址的值,又是在0x2068处,写入的0值,

这应该是在栈中初始化的一个指针,对比源码:

2 double free core dump文件分析

把core文件从开发板拷贝到本地主机,用gdb命令打开,命令格式为:

aarch64-unknown-nto-qnx7.1.0-gdb executable-file core-file

Core dump是SIGABRT 信号导致的:

并没有显示有效的出错地址:

用bt命令看一下调用栈信息:

可以看到一些调用栈信息,但并不完整,我们从头开始追溯整个调用栈:

用info all-registers看一下寄存器信息:

简单介绍一下arm64通用寄存器的基本作用。

• X0~X7:用于传递子程序参数和结果,使用时不需要保存,多余参数采用堆栈传递,64位返回结果采用X0表示,128位返回结果采用X1:X0表示。

• X8:用于保存子程序返回地址, 尽量不要使用 。

• X9~X15:临时寄存器,使用时不需要保存。

• X16~X17:子程序内部调用寄存器,使用时不需要保存,尽量不要使用。

• X18:平台寄存器,它的使用与平台相关,尽量不要使用。

• X19~X28:临时寄存器,使用时必须保存。

• X29:帧指针寄存器fp,用于连接栈帧,使用时需要保存。

• X30:链接寄存器LR

• X31:堆栈指针寄存器SP

这边重点关注sp 寄存器,这是栈的底部,以及x29寄存器,用来存储栈的顶部。

先看一下出错的pc地址,为0x782e8430

info sharedlibrary 看一下动态库的地址分布:

该地址在libc.so.5 的虚拟地址范围中(0x0000000078293000 ~0x0000000078359ee8)。

c语言函数调用的时候,整个栈空间大概是这样子的:

发生core dump时,fp的地址为0xf13ebc0, 记录该 fp为fp1,查看 该地址的值:

0x0f13ec20 为上一个fp的地址,记录为fp2,函数调用返回地址存在0xf13ebc0 +8=0xf13ebc8,为 lr2:

arm64一条指令占4个字节,PC地址还需要-4,为0x782ce77c-4=0x782ce778,为pc2,该地址还在标准库函数中,运用上面的规律,接着往前回溯: fp3为0x0f13ec60, lr3为*(0x0f13ec60+8)=0x78a65190, pc3为0x78a65190-4=0x78A6518C

0x78A6518C的地址在libqcx_max96712.so中,栈回溯到这边可以停止了。整个栈的内存分布如下图:

下面看一下0x78A6518C这个地址在libqcx_max96712.so中的位置,0x78A6518C-0x0000000078a5b000=a18c

查看反汇编文件中a18c是什么代码:

这是一个free的函数调用,其中参数为x0, sp+88的地址获得,再往前看又是一个free,也是一样的参数,说明该代码free了两次,存在问题,源码如下:

  • 20
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在QNX下调试位机(也称为嵌入式系统)的Coredump时,以下是一些基本步骤和工具: 1. 获取Coredump文件:在位机系统出现崩溃或异常时,Coredump文件会自动生成。可以通过以下命令获取Coredump文件:`core_dump_channel`。也可以使用`devc-*`命令检测异常进程并生成Coredump文件。 2. 分析Coredump文件:可以使用GNU调试器(GDB)来分析和调试Coredump文件。可以通过在命令行中输入以下命令来启动GDB:`gdb <位机可执行文件> -c <Coredump文件>`。 3. 定位问题代码:在GDB中,可以使用`bt`命令来查看函数的堆栈跟踪,以定位造成崩溃的代码。还可以使用`info registers`命令查看寄存器的数值,以了解当前状态。 4. 观察变量和内存:使用GDB,可以使用命令`print`查看变量和内存中的值。可以通过打印变量来检查其值是否正确,或者通过查看内存来了解崩溃的原因。 5. 单步调试:可以使用GDB的单步调试功能来逐行执行代码,并观察程序的行为。可以使用`next`命令来执行下一行代码,或者使用`step`命令来进入函数调用。 6. 修改代码和重新编译:在根据Coredump分析找到问题代码后,可以修改代码并重新编译。然后,您可以运行在修复后的代码上的测试,以确保解决了问题。 总之,对于QNX下的位机Coredump调试,主要使用GDB这样的调试工具来分析Coredump文件,查找问题代码,并使用单步调试等功能来定位问题和修复代码。这些步骤可以帮助我们理解和解决嵌入式系统中出现的异常和崩溃问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值