20145219 gdb调试汇编堆栈分析
20145219 gdb调试汇编堆栈分析
代码gdbdemo.c
int g(int x)
{
return x+19;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(19)+19;
}
gcc编译gdbdemo.c
-
使用
gcc -g gdbdemo.c -o gdbdemo -m32命令在64位的机器上产生32位汇编代码 -
在产生32位汇编代码时可能会出现如下错误:
![]()
-
解决方法是在终端输入如下命令:
sudo apt-get install libc6-dev-i386,安装一个库
![]()
-
安装成功后再次执行
gcc -g gdbdemo.c -o gdbdemo -m32命令就可以顺利进行下一步了
gdb调试可执行文件gdbdemo
-
使用
gdb gdbdemo指令打开gdb调试器
![]()
-
使用
break main指令在main函数处设置断点(可以使用l指令在屏幕上打印代码),然后,使用r指令运行代码,可以看到运行时在main函数位置停了下来
![]()
-
使用
disassemble指令获取汇编代码(因为之前执行的命令中有-m32,所以此处显示的是32位汇编代码)
![]()
-
用
i r指令查看各寄存器的值
![]()
-
可见此时主函数的栈基址为0xffffd058,用
x 0xffffd058指令查看内存地址中的值:
![]()
因此,目前%esp所指堆栈内容为0,%ebp所指内容也为0
-
,使用
display /i $pc(结合display命令和寄存器/pc内部变量)指令进行设置
![]()
这使得在每次执行下一条汇编语句时,都会显示出当前执行的语句,方便查看。
-
依次如下指令调试汇编代码,并查看%esp、%ebp和堆栈内容:
- 1、使用
si指令单步跟踪一条机器指令 - 2、使用
i r指令查看各寄存器的值(在这里要看%eip、%eax、%esp和%ebp) - 3、使用
x/na %esp对应的值指令查看堆栈变化
之后一直重复执行上述三步,直至结束
- 1、使用
-
main函数汇编代码
![]()
-
f函数汇编代码
![]()
-
g函数汇编代码
![]()
-
从main函数开始,
push $0x13分配4字节的栈空间,并且设置arg1=19
![]()
![]()
-
call调用f(0x80483e6)
![]()
-
执行f函数,f初始化帧指针,将上一个函数的基址入栈,将当前%esp作为新基址
![]()
-
f分配栈空间,为传参做准备
![]()
-
pushl 0x8(%ebp)将%esp中的8存入栈中
![]()
-
call调用g(0x80483db)
![]()
-
执行g函数,g初始化栈指针
![]()
-
g分配栈空间
![]()
-
pushl 0x8(%ebp)将%esp中的8存入栈中
![]()
-
将 %eax 与立即数 19 相加
![]()
-
pop %ebp在g结束前弹栈
![]()
-
ret返回g中call的调用位置,结束g函数
![]()
-
将 %esp 与立即数 4 相加
![]()
-
leave返回准备栈
![]()
-
ret返回f中call的调用位置,结束f函数
![]()
-
进入main函数,将 %esp 与立即数 4 相加
![]()
-
将 %eax 与立即数 19 相加
![]()
-
leave返回准备栈
![]()
-
ret结束main函数
![]()
gdb调试分析汇总表
| 指令 | %eip | %ebp | %esp | %eax | 堆栈 |
|---|---|---|---|---|---|
| push $0x13 | 0x80483f9 | 0xffffd058 | 0xffffd058 | 0xf7fbadbc | 0x00000000 |
| call 0x80483e6 | 0x80483fb | 0xffffd058 | 0xffffd054 | 0xf7fbadbc | 0x13 0x0 |
| push %ebp | 0x80483e6 | 0xffffd058 | 0xffffd050 | 0xf7fbadbc | 0x8048400 0x13 0x0 |
| mov %esp,%ebp | 0x80483e7 | 0xffffd058 | 0xffffd04c | 0xf7fbadbc | 0xffffd058 0x8048400 0x13 0x0 |
| pushl 0x8(%ebp) | 0x80483e9 | 0xffffd04c | 0xffffd04c | 0xf7fbadbc | 0xffffd058 0x8048400 0x13 0x0 |
| call 0x80483db | 0x80483ec | 0xffffd04c | 0xffffd048 | 0xf7fbadbc | 0x13 0xffffd058 0x8048400 0x13 0x0 |
| push %ebp | 0x80483db | 0xffffd04c | 0xffffd044 | 0xf7fbadbc | 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0 |
| mov %esp,%ebp | 0x80483dc | 0xffffd04c | 0xffffd040 | 0xf7fbadbc | 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0 |
| mov 0x8(%ebp),%eax | 0x80483de | 0xffffd040 | 0xffffd040 | 0xf7fbadbc | 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0 |
| add $0x13,%eax | 0x80483e1 | 0xffffd040 | 0xffffd040 | 0x13 | 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0 |
| pop %ebp | 0x80483e4 | 0xffffd040 | 0xffffd040 | 0x26 | 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0 |
| ret | 0x80483e5 | 0xffffd04c | 0xffffd044 | 0x26 | 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0 |
| add $0x4,%esp | 0x80483f1 | 0xffffd04c | 0xffffd048 | 0x26 | 0x13 0xffffd058 0x8048400 0x13 0x0 |
| leave | 0x80483f4 | 0xffffd04c | 0xffffd04c | 0x26 | 0xffffd058 0x8048400 0x13 0x0 |
| ret | 0x80483f5 | 0xffffd058 | 0xffffd050 | 0x26 | 0x8048400 0x13 0x0 |
| add $0x4,%esp | 0x8048400 | 0xffffd058 | 0xffffd054 | 0x26 | 0x13 0x0 |
| add $0x13,%eax | 0x8048403 | 0xffffd058 | 0xffffd058 | 0x26 | 0x0 |
| leave | 0x8048406 | 0xffffd058 | 0xffffd058 | 0x39 | |
| ret | 0x8048407 | 0x0 | 0xffffd05c | 0x39 |
































浙公网安备 33010602011771号