GDB调试汇编堆栈过程分析
GDB調(diào)試匯編堆棧過(guò)程分析
分析過(guò)程
.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位的機(jī)器上產(chǎn)生32位匯編,然后使用gdb example指令進(jìn)入gdb調(diào)試器
進(jìn)入之后先在main函數(shù)處設(shè)置一個(gè)斷點(diǎn)b main,再run一下,使用disassemble指令獲取匯編代碼,用i(info) r(registers)指令查看各寄存器的值:
可見(jiàn)此時(shí)主函數(shù)的基地址為0xffffd018,用x(examine)指令查看內(nèi)存地址中的值,但目前%esp所指堆棧內(nèi)容為0,%ebp所指內(nèi)容也為0
首先,結(jié)合display命令和寄存器或pc內(nèi)部變量,做如下設(shè)置:display /i $pc,這樣在每次執(zhí)行下一條匯編語(yǔ)句時(shí),都會(huì)顯示出當(dāng)前執(zhí)行的語(yǔ)句。下面展示每一步時(shí)%esp、%ebp和堆棧內(nèi)容的變化:用i r、查看變化 用x/2a + 地址看棧的值。
call指令將下一條指令的地址入棧,此時(shí)%esp,%ebp和堆棧的值為:
將上一個(gè)函數(shù)的基址入棧,從當(dāng)前%esp開(kāi)始作為新基址:
先為傳參做準(zhǔn)備:
實(shí)參的計(jì)算在%eax中進(jìn)行
實(shí)參入棧06
call指令將下一條指令的地址入棧
計(jì)算short+int
pop %ebp指令將棧頂彈到%ebp中,同時(shí)%esp增加4字節(jié):
ret指令將棧頂彈給%eip:
因?yàn)楹瘮?shù)f修改了%esp所以用leave指令恢復(fù)。leave指令先將%esp對(duì)其到%ebp,然后把棧頂彈給%ebp:
主函數(shù)匯編代碼,并結(jié)束棧幀的調(diào)用。
綜上可列表分析根據(jù)匯編代碼得到棧幀的調(diào)用
| 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 |
遇到的問(wèn)題及解決過(guò)程
使用-m32指令報(bào)錯(cuò):
這是因?yàn)榫幾g64位Linux版本32位的二進(jìn)制文件,需要安裝一個(gè)庫(kù),使用指令sudo apt-get install libc6-dev-i386
轉(zhuǎn)載于:https://www.cnblogs.com/20145335hh/p/6131873.html
總結(jié)
以上是生活随笔為你收集整理的GDB调试汇编堆栈过程分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Microsoft SQL Server
- 下一篇: 又一次的Microsoft Visual