GDB堆疊跟蹤與彙編除錯
堆疊跟蹤
原始碼
使用
gcc - g example.c -o example -m32
指令在64位的機器上產生32位彙編,然後使用gdb example
指令進入gdb偵錯程式:
- 在main函式處設定一個斷點,再run執行
- 使用
disassemble
獲取彙編程式碼 用
info registers
指令檢視各暫存器的值
- 由上圖知此時主函式的棧基址為0xbffff324
用
x 0xbffff324
指令檢視記憶體地址中的值
使用
display /i $pc
:在每次執行下一條彙編語句時,都會顯示出當前執行的是哪條語句
- 下面展示每一步時%esp、%ebp和堆疊內容的變化:
- call指令將下一條指令的地址入棧:
- 將上一個函式的基址入棧,從當前%esp開始作為新基址:
先為傳參做準備:
實參的計算在%eax中進行:
- 實參入棧,call指令將下一條指令的地址入棧:
- 計算short+int:
pop %ebp指令將棧頂彈到%ebp中,同時%esp增加4位元組:
ret指令將棧頂彈給%eip:
- 函式f修改了%esp,使用leave指令恢復
leave指令先將%esp對其到%ebp,然後把棧頂彈給%ebp:
執行過程中%ebp、%esp、堆疊值的變化
指令 | %esp | %ebp | 堆疊 |
---|---|---|---|
movl $0x8,(%esp) | 0xbffff324 | 0xbffff328 | 0x0 |
call 0x80483c4 | 0xbffff324 | 0xbffff328 | 0x8 0x0 |
push %ebp | 0xbffff320 | 0xbffff328 | 0x80483ee 0x8 0x0 |
mov %esp,%ebp | 0xbffff31c | 0xbffff328 | 0xbffff328 0x80483ee 0x8 0x0 |
mov 0x804a014,%eax | 0xbffff318 | 0xbffff31c | 0x8048409 0xbffff328 0x80483ee 0x8 0x0 |
call 0x80483b4 | 0xbffff318 | 0xbffff31c | 0xa 0x8048409 0xbffff328 0x80483ee 0x8 0x0 |
push %ebp | 0xbffff314 | 0xbffff31c | 0x80483da 0xa 0x8048409 0xbffff328 0x80483ee 0x8 0x0 |
mov %esp,%ebp | 0xbffff310 | 0xbffff31c | 0xbffff31c 0x80483da 0xa 0x8048409 0xbffff328 0x80483ee 0x8 0x0 |
Pop %ebp | 0xbffff310 | 0xbffff310 | 0xbffff31c 0x80483da 0xa 0x8048409 0xbffff328 0x80483ee 0x8 0x0 |
ret | 0xbffff314 | 0xbffff31c | 0x80483da 0xa 0x8048409 0xbffff328 0x80483ee 0x8 0x0 |
leave | 0xbffff318 | 0xbffff31c | 0x8048409 0xbffff328 0x80483ee 0x8 0x0 |
ret | 0xbffff320 | 0xbffff328 | 0xbffff328 0x80483ee 0x8 0x0 |
mov 0x80484d0,%edx | 0xbffff324 | 0xbffff328 | 0x8 0x0 |
add $edx,%eax | 0xbffff324 | 0xbffff328 | 0x0 |
ret | 0xbffff32c | 0x0 |
gdb小使用
使用gdb的bt/frame/up/down指令動態檢視呼叫棧幀的情況