• 20145310 GDB调试汇编堆栈分析


    GDB调试汇编堆栈分析

    由于老师说要逐条分析汇编代码,所以我学习卢肖明同学的方法,重新写了一篇博客。

    代码:

    #include<stdio.h>
    
    short addend1 = 1;
    static int addend2 = 2;
    const static long addend3 = 3;
    
    static int g(int x)
    {
    	return x + addend1;
    }  
    
    static const int f(int x)
    {
    	return g(x + addend2);
    }
    
    int main(void)
    {
    	return f(8) + addend3;
    }
    

    GCC编译

    使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器

    注:这里在我第一次做的时候出现使用-m32指令报错的现象,使用sudo apt-get install libc6-dev-i386命令安装所需库即可。

    分析代码过程

    首先进入gbd之后先在main函数处设置一个断点,再run一下,可以看到运行时在main函数位置停了下来

    使用disassemble指令获取汇编代码

    可见此时主函数的栈基址为0xffffd068,用x(examine)指令查看内存地址中的值,但目前%esp所指堆栈内容为0,%ebp所指内容也为0

    依次如下指令调试汇编代码,并查看%esp、%ebp和堆栈内容:
    1、使用si指令单步跟踪一条机器指令
    2、使用i r(info registers)指令查看各寄存器的值(在这里要看%eip、%eax、%esp和%ebp)
    3、使用x/na %esp对应的值指令查看堆栈变化

    将上一个函数的基址入栈,从当前%esp开始作为新基址:

    call指令将下一条指令的地址入栈,此时%esp,%ebp和堆栈的值为:

    先为传参做准备:

    将栈中的数据push

    leave返回准备栈

    ret结束main函数

    问题总结

    在一开始忽略了一个步骤:使用display /i $pc(结合display命令和寄存器/pc内部变量)指令进行设置,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。
    由于没有设置这个步骤,每一次都要手工输入x/I $pc,非常麻烦,好在后来改正了。

    这次的小实验让我对gdb有了深刻的理解,结合小明同学的博客,学习了gdb调试程序,设置断点等方法。其实感觉gdb在很多方面比图形调试界面还要好用,这可能就是命令行的魅力吧。
    这三周被学校结核体检折磨的够呛,总是要去医院,还要被隔离,耽误了很多很多课。如果下周二体检通过没事情了的话,课程方面落下了好多,还要很努力的去追赶吧。

    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
  • 相关阅读:
    LeetCode 1748. 唯一元素的和
    LeetCode 2047. 句子中的有效单词数
    LeetCode 1345. 跳跃游戏 IV
    LeetCode 1725. 可以形成最大正方形的矩形数目
    LeetCode 1765. 地图中的最高点
    LeetCode 2034. 股票价格波动
    LeetCode 1996. 游戏中弱角色的数量
    LeetCode 2013. 检测正方形
    LeetCode 1219. 黄金矿工
    LeetCode 2045. 到达目的地的第二短时间
  • 原文地址:https://www.cnblogs.com/pigeondandelion/p/6130033.html
Copyright © 2020-2023  润新知