20145219 gdb调试汇编堆栈分析

本文通过一个简单的C语言程序,详细介绍了如何使用GDB调试器进行32位汇编代码的调试过程,包括设置断点、查看寄存器值、跟踪函数调用等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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位汇编代码时可能会出现如下错误:
    884666-20161130135509381-109802083.png

  • 解决方法是在终端输入如下命令:sudo apt-get install libc6-dev-i386,安装一个库
    884666-20161130135542131-295282330.png

  • 安装成功后再次执行gcc -g gdbdemo.c -o gdbdemo -m32命令就可以顺利进行下一步了

gdb调试可执行文件gdbdemo

  • 使用gdb gdbdemo指令打开gdb调试器
    884666-20161130135619084-1319454312.png

  • 使用break main指令在main函数处设置断点(可以使用l指令在屏幕上打印代码),然后,使用r指令运行代码,可以看到运行时在main函数位置停了下来
    884666-20161130135633474-1751077091.png

  • 使用disassemble指令获取汇编代码(因为之前执行的命令中有-m32,所以此处显示的是32位汇编代码)
    884666-20161130135645552-2020875325.png

  • i r指令查看各寄存器的值
    884666-20161130135658021-1543240125.png

  • 可见此时主函数的栈基址为0xffffd058,用x 0xffffd058指令查看内存地址中的值:
    884666-20161130135713771-1643247910.png

    因此,目前%esp所指堆栈内容为0,%ebp所指内容也为0

  • ,使用display /i $pc(结合display命令和寄存器/pc内部变量)指令进行设置
    884666-20161130135849740-833269247.png

    这使得在每次执行下一条汇编语句时,都会显示出当前执行的语句,方便查看。

  • 依次如下指令调试汇编代码,并查看%esp、%ebp和堆栈内容:

    • 1、使用si指令单步跟踪一条机器指令
    • 2、使用i r指令查看各寄存器的值(在这里要看%eip、%eax、%esp和%ebp)
    • 3、使用x/na %esp对应的值指令查看堆栈变化

    之后一直重复执行上述三步,直至结束

  • main函数汇编代码
    884666-20161130135921631-1112458214.png

  • f函数汇编代码
    884666-20161130135932146-1210356417.png

  • g函数汇编代码
    884666-20161130135940099-1028163714.png

  • 从main函数开始,push $0x13分配4字节的栈空间,并且设置arg1=19
    884666-20161130140025209-520712058.png

    884666-20161130140041365-260889848.png

  • call调用f(0x80483e6)
    884666-20161130140319302-1226733355.png

  • 执行f函数,f初始化帧指针,将上一个函数的基址入栈,将当前%esp作为新基址
    884666-20161130140407927-587135288.png

  • f分配栈空间,为传参做准备
    884666-20161130140423381-648160153.png

  • pushl 0x8(%ebp)将%esp中的8存入栈中
    884666-20161130140441474-71291806.png

  • call调用g(0x80483db)
    884666-20161130140452427-1724845289.png

  • 执行g函数,g初始化栈指针
    884666-20161130140502568-107072226.png

  • g分配栈空间
    884666-20161130140512818-47072597.png

  • pushl 0x8(%ebp)将%esp中的8存入栈中
    884666-20161130140523256-358755259.png

  • 将 %eax 与立即数 19 相加
    884666-20161130140532209-567721579.png

  • pop %ebp在g结束前弹栈
    884666-20161130140545990-553521434.png

  • ret返回g中call的调用位置,结束g函数
    884666-20161130140554412-1282351275.png

  • 将 %esp 与立即数 4 相加
    884666-20161130140602490-485550422.png

  • leave返回准备栈
    884666-20161130140611693-2012263760.png

  • ret返回f中call的调用位置,结束f函数
    884666-20161130140624771-612272779.png

  • 进入main函数,将 %esp 与立即数 4 相加
    884666-20161130140636709-1633914849.png

  • 将 %eax 与立即数 19 相加
    884666-20161130140645474-1405259208.png

  • leave返回准备栈
    884666-20161130140653381-1078492053.png

  • ret结束main函数
    884666-20161130140703756-1434007173.png

gdb调试分析汇总表

指令%eip%ebp%esp%eax堆栈
push $0x130x80483f90xffffd0580xffffd0580xf7fbadbc0x00000000
call 0x80483e60x80483fb0xffffd0580xffffd0540xf7fbadbc0x13 0x0
push %ebp0x80483e60xffffd0580xffffd0500xf7fbadbc0x8048400 0x13 0x0
mov %esp,%ebp0x80483e70xffffd0580xffffd04c0xf7fbadbc0xffffd058 0x8048400 0x13 0x0
pushl 0x8(%ebp)0x80483e90xffffd04c0xffffd04c0xf7fbadbc0xffffd058 0x8048400 0x13 0x0
call 0x80483db0x80483ec0xffffd04c0xffffd0480xf7fbadbc0x13 0xffffd058 0x8048400 0x13 0x0
push %ebp0x80483db0xffffd04c0xffffd0440xf7fbadbc0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
mov %esp,%ebp0x80483dc0xffffd04c0xffffd0400xf7fbadbc0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
mov 0x8(%ebp),%eax0x80483de0xffffd0400xffffd0400xf7fbadbc0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
add $0x13,%eax0x80483e10xffffd0400xffffd0400x130xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
pop %ebp0x80483e40xffffd0400xffffd0400x260xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
ret0x80483e50xffffd04c0xffffd0440x260x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
add $0x4,%esp0x80483f10xffffd04c0xffffd0480x260x13 0xffffd058 0x8048400 0x13 0x0
leave0x80483f40xffffd04c0xffffd04c0x260xffffd058 0x8048400 0x13 0x0
ret0x80483f50xffffd0580xffffd0500x260x8048400 0x13 0x0
add $0x4,%esp0x80484000xffffd0580xffffd0540x260x13 0x0
add $0x13,%eax0x80484030xffffd0580xffffd0580x260x0
leave0x80484060xffffd0580xffffd0580x39
ret0x80484070x00xffffd05c0x39

参考资料

转载于:https://www.cnblogs.com/20145219songge/p/6117547.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值