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 |
参考资料
最新文章
- EC笔记,第二部分:8.别让异常逃离析构函数
- 保持const和non-const函数代码的一致
- iOS 多渠道打包 编译脚本
- testng环境设置
- js join()函数将数组转换成字符串
- [译]Stairway to Integration Services Level 6 - SSIS 工作流管理基础
- MySQL 修改最大连接数
- 201521123070 《JAVA程序设计》第12周学习总结
- Solidity constant view pure关键字的区别与联系
- Tomcat FAIL - Deploy Upload Failed, Exception: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (110960596) exceeds the confi
- 委托(Delegate)简介
- java 自动补全
- linux 断网 扫描基本命令
- C#调用免费天气预报WebService
- JSON与XML的区别比较(转)
- 用shell实现bat批处理的pause命令-追加改进
- mdev自动创建和删除设备节点
- forward_list
- 简单的PHP算法题
- Cinder Columns
热门文章
- Effective Java 34 Emulate extensible enums with interfaces
- oracle中的数值函数整理
- 【mysql】关于innodb_file_format
- 第二篇 :微信公众平台开发实战Java版之开启开发者模式,接入微信公众平台开发
- C++ new(1)
- CANopen DS301协议中文翻译V03版
- 怎样用ZBrush雕刻人体造型
- ACdream OJ 1099 瑶瑶的第K大 --分治+IO优化
- 利用jquery来进行表单的多向提交
- 数字对 (长乐一中模拟赛day2T2)