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=19call调用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 |