gdb如何从堆栈破坏的堆栈中定位问题(ucontext_t)

当gdb堆栈破坏时,如果有ucontext_t进程上下文信息,仍能进行调试。通过查看log的Stacktrace、分析coredump、理解用户进程上下文中的信息(如fault_address、regs、sp、pc等),可以定位到问题。在本例中,通过LR寄存器和X11_DispatchFocusOut函数,发现是多线程环境下指针越界导致的段错误,最终确认为多线程同步问题。
摘要由CSDN通过智能技术生成

对于大多数gdb堆栈破坏的情况,查问题时只能缩小问题代码范围,不断测试复现,找出容易复现的方式,一步步解决。但是有一种情况,如果你的gdb堆栈破坏了,但是有ucontext_t进程上下文信息,那么是可以继续分析的!本文介绍了gdb堆栈破坏但有ucontext_t进程上下文信息的前提下使用gdb调试定位问题的过程。

1 使用带有debug信息的动态库(SDL,X11)

Linux根据xxx.so下载xxx源码,编译和安装_u012906122的专栏-CSDN博客

2 查看log的Stack trace

Segmentation fault(Invalid permisssions for mapped object [0xffff28207220])

访问的内存地址无效!!!

3 gdb coredump

gdb xxx core_xxx_3255

发现gdb堆栈被破坏了

看下sig_handler函数:

handleSignal函数:

从以上信息可以推断出来,void* ctx的实际类型是struct ucontext_t* ctx。

4 查看用户进程上下文信息

p *(struct ucontext_t*) 0xffff6a7f9cf0

目前觉得uc_mcontext里有用的用户进程上下文信息:

(1) fault_address

(2) regs

对于arm64 cpu,有32个regs:

x0~x7:传递程序参数,多余参数采用堆栈传递

x29:FP栈框指针

x30:LR程序连接寄存器,保存函数调用的返回地址.

x31:SP堆栈指针

(3) sp

(4) pc

(5) __reserved

下面逐个分析用户进程上下文信息:

(1)fault_address,pc

pc指针可能访问了一个非法的内存地址导致段错误

(2)通过LR程序连接寄存器,查看函数调用的返回地址

info symbol xxx:用于查看该地址的符号

p/x 281472886753104(x30,LR寄存器)

info symbol 0xffff836dc750

说明是在X11_DispatchFocusOut里出现指针越界的情况

(3)__reserved信息

info types xxx:用于查看该类型符号

info types ucontext_t

官方注释:

vim /usr/include/aarch64-linux-gnu/sys/ucontext.h

__reserved表示出现崩溃前的信息,保存了CPU额外的状态信息如FP/SIMD状态.FP是栈框指针。

这个变量很有用,如果崩溃附近的代码有打印,会保存打印的内容。

__reserved信息:

看下代码里在哪里:

grep "FocusOut2 data->ic" ./ -R -n

结合以上信息可以推断出来,崩溃是在X11_DispatchFocusOut接口里,可能与X11_XUnsetICFocus有关.

5 分析X11_XUnsetICFocus接口

info functions xxx:用于查看该函数符号信息

info functions XUnsetICFocus

(1) 分析XUnsetICFocus代码流程

(2)反汇编XUnsetICFocus,结合ucontext_t分析寄存器信息

disassemble XUnsetICFocus

ldr:LDR R0,[R1]      将存储器地址为R1的字数据读入寄存器R0.                  //32位cpu是一个字是4个字节,64位cpu一个字是8个字节。

ldr x2,[x0,#8]      将x0偏移8个字节的地址里的字数据读入到寄存器x2.           //在64位机上,指针占用内存大小:8个字节

cbz:compare branch zero

br:branch register

以上信息推断出来,只是读了x0寄存器,ucontext_t中的x0是有效的.

(3)gdb跟踪变量

[1] x0:

methods:0xffff282bfab0

崩溃的pc指针地址就是这个地址(0xffff28207220)!

[2] x1:

x1寄存器的值就是非法的内存地址!

即上图位置出错。即下图代码中第359行,函数指针地址错误!即函数指针变为野指针,怀疑可能其他地方(多线程)在修改它。

6 info sharedlibrary确定地址越界

info sharedlibrary

0xffff28207220不在X11.so有效范围内.

7 梳理代码流程,定位问题根因

既然怀疑多线程导致,在所有调用data->ic处加打印线程id,复现:

蓝色框是thread1,红色框是thread2。

结论:验证猜测,是多线程问题,先析构后调用导致访问野指针越界。

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值