GDB调试汇编堆栈过程分析
GDB调试汇编堆栈过程分析
代码如下:
使用gcc –S –o 20145211shiyanlou.s 20145211.c -m32编译
- 20145211shiyanlou.s文件如下:
删除gcc产生代码中以"."开头的编译器指令,分析汇编语言
-
保存%ebp,并设置新的帧指针
-
pushl $8分配4字节的栈空间
-
call调用f,f初始化帧指针,分配栈空间
-
在f中第六句call调用g,g被调用,初始化栈指针,分配栈空间,将%eax与立即数15相加,弹栈
-
执行ret返回f中call的调用位置
-
f结束,返回main中call调用的位置
-
main %eax加15
-
leave为返回准备栈,相当于%ebp出栈,最后ret结束gdb调试可执行文件
gdb调试可执行文件
-
使用
gdb gdbdemo
指令打开gdb调试器 -
使用
break main
指令在main函数处设置断点(可以使用l
指令在屏幕上打印代码),然后,使用r
指令运行代码,可以看到运行时在main函数位置停了下来;并使用disassemble指令获取汇编代码(因为之前执行的命令中有-m32,所以此处显示的是32位汇编代码) -
-
使用display /i $pc(结合display命令和寄存器/pc内部变量)指令进行设置
- 可见此时主函数的栈基址为0xffffd068,用x(examine)指令查看内存地址中的值,但目前%esp所指堆栈内容为0,%ebp所指内容也为0
- 用i r指令查看各寄存器的值
- 依次如下指令调试汇编代码,并查看%esp、%ebp和堆栈内容:
- 1、使用
si
指令单步跟踪一条机器指令 - 2、使用
i r
指令查看各寄存器的值(在这里要看%eip、%eax、%esp和%ebp) - 3、使用
x/na %esp对应的值
指令查看堆栈变化 - 之后一直重复执行上述三步,直至结束
- call调用f(0x80483ef)
-
执行f函数,f初始化帧指针,将上一个函数的基址入栈,将当前%esp作为新基址
-
call指令将下一条指令的地址入栈,此时%esp,%ebp和堆栈的值为:0xffffcfa0,0xffffcfa8
- 为传参做准备,将0x804a01c的值存入%edx中
- 将栈中的数据push
-
leave返回准备栈ret结束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 |
总结体会
这次的学习虽然还未完全掌握利用gdb对汇编代码的调试,但使我对gdb有了更深的认识。汇编代码是一种机器语言,理解起来较为困难,没有高级语言那样容易。
不过万变不离其宗,只要肯下功夫,还是可以取得较大收获的。