Linux反汇编根据程序崩溃堆栈信息定位问题1
写应用程序时时常出现程序异常崩溃退出,这里总结Linux反汇编根据程序崩溃堆栈信息定位问题的方法。程序崩溃堆栈信息使用命令dmesg查看:ifotond: unhandled page fault (11) at 0x00000000, code 0x017pgd = c64e8000[00000000] *pgd=864f1835, *pte=00000000, *ppte=0...
写应用程序时时常出现程序异常崩溃退出,这里总结Linux反汇编根据程序崩溃堆栈信息定位问题的方法。
程序崩溃堆栈信息
使用命令dmesg查看:
ifotond: unhandled page fault (11) at 0x00000000, code 0x017
pgd = c64e8000
[00000000] *pgd=864f1835, *pte=00000000, *ppte=00000000
CPU: 0 PID: 3327 Comm: ifotond Not tainted 4.9.11 #2
Hardware name: Freescale i.MX6 UltraLite (Device Tree)
task: c6fa0000 task.stack: c64ca000
PC is at 0xb6c26e64
LR is at 0x5c6ac
pc : [<b6c26e64>] lr : [<0005c6ac>] psr: 600d0030
sp : bedb2b90 ip : ffffffff fp : bedb2c44
r10: 00074524 r9 : 0105e648 r8 : 00076b40
r7 : 0105e653 r6 : 00000000 r5 : bedb2bb4 r4 : 00000000
r3 : 00003030 r2 : 00000000 r1 : 00000000 r0 : fffffff8
Flags: nZCv IRQs on FIQs on Mode USER_32 ISA Thumb Segment user
Control: 10c53c7d Table: 864e8059 DAC: 00000055
CPU: 0 PID: 3327 Comm: ifotond Not tainted 4.9.11 #2
Hardware name: Freescale i.MX6 UltraLite (Device Tree)
[<c010e540>] (unwind_backtrace) from [<c010b61c>] (show_stack+0x18/0x1c)
[<c010b61c>] (show_stack) from [<c0113300>] (__do_user_fault+0x84/0xcc)
[<c0113300>] (__do_user_fault) from [<c01135b8>] (do_page_fault+0x270/0x314)
[<c01135b8>] (do_page_fault) from [<c0101324>] (do_DataAbort+0x3c/0xbc)
[<c0101324>] (do_DataAbort) from [<c010c41c>] (__dabt_usr+0x3c/0x40)
Exception stack(0xc64cbfb0 to 0xc64cbff8)
bfa0: fffffff8 00000000 00000000 00003030
bfc0: 00000000 bedb2bb4 00000000 0105e653 00076b40 0105e648 00074524 bedb2c44
bfe0: ffffffff bedb2b90 0005c6ac b6c26e64 600d0030 ffffffff
反汇编
arm-linux-gnueabihf-objdump -d ~/ifotond > ~/ifoton.s
反汇编的可执行文件不能被strip掉,否则不能得到函数信息。【not stripped】
查看反汇编文件
0005c59c <config_ts>:
5c59c: e92d48f0 push {r4, r5, r6, r7, fp, lr}
5c5a0: e28db014 add fp, sp, #20
5c5a4: e24dd098 sub sp, sp, #152 ; 0x98
5c5a8: e52de004 push {lr} ; (str lr, [sp, #-4]!)
5c5ac: fafed0f4 blx 10984 <__gnu_mcount_nc>
5c5b0: e3500000 cmp r0, #0
5c5b4: e3a03000 mov r3, #0
省略。。。。。。。。。
5c698: e24b008b sub r0, fp, #139 ; 0x8b
5c69c: ebfeb64f bl 9fe0 <_init+0x378>
5c6a0: e51b6094 ldr r6, [fp, #-148] ; 0x94
5c6a4: e1a00006 mov r0, r6
-> [5c6a8]: ebfeb63a bl 9f98 <_init+0x330>
-> [5c6ac]: e6ff1070 uxth r1, r0
5c6b0: e1a02004 mov r2, r4
5c6b4: e1a00006 mov r0, r6
5c6b8: ebffdbe2 bl 53648 <param_setapn>
5c6bc: e55b0099 ldrb r0, [fp, #-153] ; 0x99
5c6c0: e1a01005 mov r1, r5
分析
PC is at 0xb6c26e64,由于反汇编文件中搜索不到,估计是已经被改,所以继续找到下一条指令LR is at 0x5c6ac,可以看到信息:5c6ac: e6ff1070 uxth r1, r0,查看r1和r0的信息:r1 : 00000000 r0 : fffffff8,怀疑应该是操作到空指针了。
5c6ac前面一句指令是bl 9f98 <_init+0x330>,由于没有函数名,推测是系统调用,所以这行汇编指令是系统调用,后面调用的是param_setapn函数,怀疑系统调用函数传入的参数有空指针。
找到0005c59c <config_ts>信息中的config_ts函数:
static inline int8_t config_ts(char *args)
{
uint8_t idx;
uint8_t *ip = NULL;
char *apn = NULL;
/* 2.解析参数
* idx,srvid,ip,port,apn
*/
utils_mem_scannf(&args[4], strlen(args) - 4, "%d,%d,%s,%d,%s\n", \
&idx, &tsp.srvid, &ip, &tsp.addr.port, &apn);
if(NULL != ip)memcpy(tsp.addr.ip.data, ip, tsp.addr.ip.len);
param_setapn(apn, strlen(apn), idx);
可以看到函数param_setapn前面的函数调用是strlen,strlen引起死机问题很大可能是传入的参数是空指针,下面验证。
可以看到系统调用memcpy中的ip是有判断NULL的,所以需要确认ip地址的长度是否越界,还需确认param_setapn函数参数apn是否为NULL。
通过添加查看代码和添加打印,由于代码需要5个参数,而在测试中只传入4个参数,导致了apn为NULL,但在使用时又没有判断NULL,导致了strlen访问到空指针引起程序崩溃。
总结
C语言的指针使用很频繁,且需要自己管理内存和指针,需要特别的注意,多做容错处理,多考虑异常情况,规范自己的代码风格防止写出BUG。
更多推荐
所有评论(0)