GDB调试汇编堆栈过程分析
GDB調試匯編堆棧過程分析
分析過程
.c代碼文件
#include<stdio.h>short addend1 = 1;static int addend2 = 2;const static long addend3 = 3;static int g(int x){return x + addend1;} static const int f(int x){return g(x + addend2);}int main(void){return f(8) + addend3;}使用gcc - g example.c -o example -m32指令在64位的機器上產生32位匯編,然后使用gdb example指令進入gdb調試器
進入之后先在main函數處設置一個斷點b main,再run一下,使用disassemble指令獲取匯編代碼,用i(info) r(registers)指令查看各寄存器的值:
可見此時主函數的基地址為0xffffd018,用x(examine)指令查看內存地址中的值,但目前%esp所指堆棧內容為0,%ebp所指內容也為0
首先,結合display命令和寄存器或pc內部變量,做如下設置:display /i $pc,這樣在每次執行下一條匯編語句時,都會顯示出當前執行的語句。下面展示每一步時%esp、%ebp和堆棧內容的變化:用i r、查看變化 用x/2a + 地址看棧的值。
call指令將下一條指令的地址入棧,此時%esp,%ebp和堆棧的值為:
將上一個函數的基址入棧,從當前%esp開始作為新基址:
先為傳參做準備:
實參的計算在%eax中進行
實參入棧06
call指令將下一條指令的地址入棧
計算short+int
pop %ebp指令將棧頂彈到%ebp中,同時%esp增加4字節:
ret指令將棧頂彈給%eip:
因為函數f修改了%esp所以用leave指令恢復。leave指令先將%esp對其到%ebp,然后把棧頂彈給%ebp:
主函數匯編代碼,并結束棧幀的調用。
綜上可列表分析根據匯編代碼得到棧幀的調用
| push $0x8 | 0x804840b | 0xffffd018 | 0xffffd018 | 0xf7fbadbc | 0x0 |
| call 0x80483ef | 0x804840d | 0xffffd018 | 0xffffd014 | 0xf7fbadbc | 0x8 0x0 |
| push %ebp | 0x80483ef | 0xfffffd018 | 0xffffd010 | 0xf7fbadbc | 0xffffd018 0x8048412 0x8 0x0 |
| mov 0x804a01c,%edx | 0x80483f2 | 0xffffd00c | 0xffffd00c | 0xf7fbadbc | 0xffffd018 0x8048412 0x8 0x0 |
| mov 0x8(%ebp),%eax | 0x80483f8 | 0xffffd00c | 0xffffd00c | 0xf7fbadbc | 0xffffd018 0x8048412 0x8 0x0 |
| add %edx,%eax | 0x80483fb | 0xffffd00c | 0xffffd00c | 0x8 | 0xffffd018 0x8048412 0x8 0x0 |
| push %eax | 0x80483fd | 0xffffd00c | 0xffffd00c | 0xa | 0xffffd018 0x8048412 0x8 0x0 |
| call 0x80483db | 0x80483fe | 0xffffd00c | 0xffffd008 | 0xa | 0xa 0xffffd018 0x8048412 0x8 0x0 |
| push %ebp | 0x80483db | 0xffffd00c | 0xffffd004 | 0xa | 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| mov %esp,%ebp | 0x80483dc | 0xffffd00c | 0xffffd000 | 0xa | 0xffffd00c 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| movzwl 0x804a018,%eax | 0x80483de | 0xffffd000 | 0xffffd000 | 0xa | 0xffffd00c 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| movswl %ax,%edx | 0x80483e5 | 0xffffd000 | 0xffffd000 | 0x1 | 0xffffd00c 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| mov 0x8(%ebp),%eax | 0x80483e8 | 0xffffd000 | 0xffffd000 | 0x1 | 0xffffd00c 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| add %edx,%eax | 0x80483eb | 0xffffd000 | 0xffffd000 | 0xa | 0xffffd00c 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| pop %ebp 0xffffcf80 | 0x80483ed | 0xffffd000 | 0xffffd000 | 0xb | 0xffffd00c 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| ret | 0x80483ee | 0xffffd00c | 0xffffd004 | 0xb | 0x8048403 0xa 0xffffd018 0x8048412 0x8 0x0 |
| add $0x4,%esp | 0x8048403 | 0xffffd00c | 0xffffd008 | 0xb | 0xa 0xffffd018 0x8048412 0x8 0x0 |
| leave | 0x8048406 | 0xffffd00c | 0xffffd00c | 0xb | 0xffffd018 0x8048412 0x8 0x0 |
| ret | 0x8048407 | 0xffffd018 | 0xffffd010 | 0xb | 0x8048412 0x8 0x0 |
| add $0x4,%esp | 0x8048412 | 0xffffd018 | 0xffffd014 | 0xb | 0x8 0x0 |
| mov $0x3,%edx | 0x8048415 | 0xffffd018 | 0xffffd018 | 0xb | 0x0 |
| add %edx,%eax | 0x804841a | 0xfffd018 | 0xffffd018 | 0xb | 0x0 |
| leave | 0x804841c | 0xffffd018 | 0xffffd018 | 0xe | 0x0 |
| ret | 0x804841d | 0x0 | 0xffffd01c | 0xe |
遇到的問題及解決過程
使用-m32指令報錯:
這是因為編譯64位Linux版本32位的二進制文件,需要安裝一個庫,使用指令sudo apt-get install libc6-dev-i386
轉載于:https://www.cnblogs.com/20145335hh/p/6131873.html
總結
以上是生活随笔為你收集整理的GDB调试汇编堆栈过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Microsoft SQL Server
- 下一篇: Fragment使用LocalBroad