debug: 反汇编debug流程(kernel、smaps、addr2line)

问题背景:

查一个概率性出现的问题,与运行环境有关且无法coredump和attach,最后请教大神解决了。解决过程颇有演绎推理的感觉,遂记录于此。详细可见 https://blog.csdn.net/l316194152/article/details/108563637

简要描述:

一、修改系统内核,在出错处截获信号进入循环。
二、复现问题,获取指针地址A和进程号B。
三、根据B进程的smaps内存映射表,由A所在地址区间得到出错的库,记录库的起始地址C。
四、A-C=D,再对库进行反汇编,得到偏移量D所属的函数。
五、甩锅,把问题甩出去。

具体步骤:

1、修改系统内核,在出错处截获信号进入循环。

diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index a9ee0d9dc740..73b52806f1f1 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -175,9 +175,15 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
                       tsk->comm, sig, addr, fsr);
                show_pte(tsk->mm, addr);
                show_regs(regs);
+               ret = sig_kernel_coredump(SIGSEGV);
+               printk(KERN_DEBUG "ret is %d\n", ret);
+               while(1);
        }
#endif

Q:为什么加在这个函数?
A:看第二步即可知,出错时,kernel有运行到此函数。

2、复现问题,获取指针地址A和进程号B

[   28.587915] xxx.cgi: unhandled page fault (11) at 0x00000008, code 0x017
[   28.587934] pgd = 6510e4e1
[   28.588024] [00000008] *pgd=28844835, *pte=00000000, *ppte=00000000
[   28.588057] CPU: 1 PID: 897 Comm: xxx.cgi Tainted: G           O      4.19.111
[   28.588066] Hardware name: Generic DT based system
[   28.588078] PC is at 0xa6774b8c
[   28.588086] LR is at 0xa5e005e0
[   28.588094] pc : [<a6774b8c>]    lr : [<a5e005e0>]    psr: a00e0010
[   28.588101] sp : a67059d0  ip : a5e005d8  fp : a6705f7c
[   28.588109] r10: a6ecc60c  r9 : a679169c  r8 : aedd3986
[   28.588117] r7 : a6ecc5dc  r6 : 00000000  r5 : a6ecc5d8  r4 : a67059dc
[   28.588124] r3 : a5e00010  r2 : 00000000  r1 : 00000000  r0 : a5e005d8
[   28.588133] Flags: NzCv  IRQs on  FIQs on  Mode USER_32  ISA ARM  Segment user
[   28.588143] Control: 10c5387d  Table: 3496006a  DAC: 00000055
[   28.588154] CPU: 1 PID: 897 Comm: sss.cgi Tainted: G           O      4.19.111
[   28.588161] Hardware name: Generic DT based system
[   28.588191] [<b010f408>] (unwind_backtrace) from [<b010b96c>] (show_stack+0x10/0x14)
[   28.588209] [<b010b96c>] (show_stack) from [<b08076e4>] (dump_stack+0x90/0xa4)
[   28.588229] [<b08076e4>] (dump_stack) from [<b011376c>] (__do_user_fault+0x160/0x174)
[   28.588246] [<b011376c>] (__do_user_fault) from [<b01139c0>] (do_page_fault+0x240/0x348)
[   28.588260] [<b01139c0>] (do_page_fault) from [<b0113c58>] (do_DataAbort+0x4c/0xec)
[   28.588274] [<b0113c58>] (do_DataAbort) from [<b0101d7c>] (__dabt_usr+0x3c/0x40)
[   28.588283] Exception stack(0xcb9c9fb0 to 0xcb9c9ff8)
[   28.588294] 9fa0:                                     a5e005d8 00000000 00000000 a5e00010
[   28.588305] 9fc0: a67059dc a6ecc5d8 00000000 a6ecc5dc aedd3986 a679169c a6ecc60c a6705f7c
[   28.588316] 9fe0: a5e005d8 a67059d0 a5e005e0 a6774b8c a00e0010 ffffffff

注意其中的
[ 28.588057] CPU: 1 PID: 897 Comm: xxx.cgi Tainted: G O 4.19.111
[ 28.588078] PC is at 0xa6774b8c
0xa6774b8c即为指针地址A,进程号B为897 。

3、根据B进程的smaps内存映射表,由A所在地址区间得到出错的库,记录库的起始地址C。

cd /proc/$B
cat smaps|grep $A

注意: 有时候grep地址A没有结果,这时候可以改为grep前两位,比如地址为a6764000,则grep a67即可。

4、A-C=D,再对库进行反汇编,得到偏移量D所属的函数。
第三步可以看到类似下面样式的信息
a6764000-a6780000 r-xp 00000000 b3:06 1743 /usr/lib/libxxx.so.0.0.0

接下来就是十六进制计算了,hex(0xa6774b8c-a6764000) = 0x10b8c

把运行环境下的这个/usr/lib/libxxx.so.0.0.0库pull出来,或者push一个addr2line进去都行。
arm-linux-gnueabihf-addr2line 0x10b8c -e libxxx.so.0.0.0 -f -C -s
即可得到出错函数名

5、甩锅,把问题甩出去
如果这个函数是你写的,那没得说,自己改吧。

但如果你已经成功得到了函数名,并且不是你写的,而是调用的外部接口,那么恭喜你,可以把这个锅甩出去了。

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值