1) 编译的时候添加编译选项
-fstack-protector 和 -fstack-protector-all 这两个选项指示编译器开启栈保护,这样在栈乱序的第一时间可以dump出来现场。可加在Makefile里面, 顺便扯一句,Makefile这种东西对于搞开源软件的人,还真是得精通,我随便想写个Makefile玩着,突然感觉自己头脑一片空白。
-fno-omit-frame-pointer 一个带帧指针和调试信息的版本
或者安装 debug info 包
2)x/xxxa 0x124578
遇到一个堆栈:
(gdb) bt
#0 0x41af821c in free () from /lib/libc.so.6
#1 0x00b28acc in ?? ()
#2 0x00b28acc in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
查看寄存器信息
r0 0x41bb44e0 1102791904
r1 0x20500 132352
r2 0x0 0
r3 0x0 0
r4 0xb28acc 11700940
r5 0xb28ce8 11701480
r6 0x460c2bdc 1175202780
r7 0x460c4920 1175210272
r8 0x0 0
r9 0x460c4460 1175209056
r10 0x400a4000 1074413568
r11 0x460c2be4 1175202788
r12 0x401a8040 1075478592
sp 0x460c2b80 0x460c2b80
lr 0x40192d84 1075391876
pc 0x41af821c 0x41af821c <free+148>
cpsr 0x20000010 536870928
查看$sp附近的地址符号信息:
(gdb) x/128a $sp-64
0x460c2b40: 0x2424 0x460c4920 0x1aa54c 0x0
0x460c2b50: 0x0 0x5 0xa0 0x400a4000
0x460c2b60: 0x460c2be4 0x4008bac4 <_dl_fixup+200> 0x400a1708 0x1
0x460c2b70: 0x5 0x0 0x0 0x40192d84 <__free_tcb+100>
0x460c2b80: 0xb28acc 0x401941c8 <pthread_join+240> 0x401940a8 <cleanup> 0xb28ce8
0x460c2b90: 0x152 0x0 0x0 0xa7a7
0x460c2ba0: 0xc40c38 0x460c3d70 0x152 0x0
0x460c2bb0: 0x0 0x2b354 <video_pipline_common::media_vpss_continued_stop()+88> 0xb27430 0x460c2bd4
0x460c2bc0: 0xa311b3 0x460c2bdc 0x1000 0xb2742c
0x460c2bd0: 0x5198 0xb28aa0 0x460c2bec 0x0
0x460c2be0: 0x460c2c0c 0x23dec <media_process::online_callback_by_winslot(int)+132> 0x460c2c0c 0x132b0 <director_driver2::get_resouce_ctx_by_res_id(int)+68>
0x460c2bf0: 0x5 0xb27410 0x2 0xb27450
0x460c2c00: 0xb27430 0xb28aa0 0x460c2c3c 0x1301c <director_driver2::ddr_transit_receive_msg(int, int, void*, void*)+504>
0x460c2c10: 0x180684 <_ZZN10RtspStream12InviteStreamEvE12__FUNCTION__> 0xe 0xb27410 0x0
0x460c2c20: 0x11f6 0x5 0x1802a0 0x2
0x460c2c30: 0xc1cb90 0xb27410 0x460c2c84 0x33134 <RtspMediaReceiveCallBack(void*, RTSP_STREAM_DATA*)+496>
0x460c2c40: 0x28 0x1803e0 0x460c2c94 0x0
0x460c2c50: 0x0 0x0 0x460c2d14 0xc3dae0
0x460c2c60: 0x0 0x460c2d14 0xc1dfd0 0xc3dae0
0x460c2c70: 0xa7a7 0xc40c38 0x460c3d70 0x152
0x460c2c80: 0x460c3d84 0xca234 <RtspStream::InviteStream()+2916> 0xe9 0x28
0x460c2c90: 0x1803e0 0xc40c68 0x1802d0 0x0
0x460c2ca0: 0x1000 0xc40dd0 0x0 0xc40c38
0x460c2cb0: 0x0 0x63617274 0x316b 0x0
然后我反汇编free 和_free_tcb两个函数,发现两个函数没有对SP做很大的操作,即__free_tcb的返回地址就在sp附近可以看出是pthread_join.
Dump of assembler code for function __free_tcb:
0x40192d20 <+0>: push {r4, lr}
0x40192d24 <+4>: add r2, r0, #132 ; 0x84
0x40192d28 <+8>: mov r4, r0
0x40192d2c <+12>: ldr r3, [r4, #132] ; 0x84
0x40192d30 <+16>: dmb sy
0x40192d34 <+20>: orr r0, r3, #32
0x40192d38 <+24>: ldrex r1, [r2]
0x40192d3c <+28>: cmp r1, r3
0x40192d40 <+32>: bne 0x40192d50 <__free_tcb+48>
0x40192d44 <+36>: strex r12, r0, [r2]
(gdb) disassemble free
Dump of assembler code for function free:
0x41af8188 <+0>: ldr r3, [pc, #160] ; 0x41af8230 <free+168>
0x41af818c <+4>: ldr r2, [pc, #160] ; 0x41af8234 <free+172>
0x41af8190 <+8>: push {lr} ; (str lr, [sp, #-4]!)
0x41af8194 <+12>: add r3, pc, r3
0x41af8198 <+16>: ldr r3, [r3, r2]
0x41af819c <+20>: ldr r3, [r3]
0x41af81a0 <+24>: cmp r3, #0
0x41af81a4 <+28>: bne 0x41af8224 <free+156>
0x41af81a8 <+32>: cmp r0, #0
0x41af81ac <+36>: popeq {pc} ; (ldreq pc, [sp], #4)
0x41af81b0 <+40>: ldr r3, [r0, #-4]
0x41af81b4 <+44>: sub r1, r0, #8
0x41af81b8 <+48>: tst r3, #2
0x41af81bc <+52>: beq 0x41af8200 <free+120>
0x41af81c0 <+56>: ldr r2, [pc, #112] ; 0x41af8238 <free+176>
pthread_join:
struct pthread *pd = (struct pthread *) threadid;
......
if (__glibc_likely (result == 0))
{
/* We mark the thread as terminated and as joined. */
pd->tid = -1;
/* Store the return value if the caller is interested. */
if (thread_return != NULL)
*thread_return = pd->result;
/* Free the TCB. */
__free_tcb (pd);
}
else
pd->joinid = NULL;
想打印(struct pthread *) threadid 的时候,发现glibc的库不是debug不能打印。