堆栈帧和gdb

时间:2015-08-14 01:37:52

标签: c gdb stack reverse-engineering

我反对改造。我编写了以下C代码,以帮助我更多地了解堆栈帧。

const int base = 16;
const int maxn = 16;

int hv[256];
int state[maxn];

void preprocess() 
{
    hv['O'] = 0;
    hv['X'] = 1;
    hv['-'] = 2;
    ...
}

// may instead use std::map<int,int>
int mapt() 
{
    switch(hashkey) {
        case ..: return 0;
        ...
    }
}

int hash(char *st) {
    int ret = 0;
    for (int i = 0; i < maxn; ++i) {
        ret = ret*base + hv[ st[i] ];
    }
    return mapt(ret);
}

int GetPot()
{
    ...
    return hash(state);
}

据我所知每次调用一个函数 创建堆栈框架(请参阅:ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_41.html)。所以,我对上述C代码的目标是至少看到三个堆栈帧。

1)主要功能 - 堆栈帧

2)求和函数 - 堆栈帧

3)媒体功能 - 堆栈帧

BTW:那些printfs只是为了帮助我跟随&#39; gdb中的程序。 =)

所以我想如果在调用sum函数之后,在程序启动后将 info frame 的输出与 info frame 的输出进行比较,我会得到不同的输出?你没看到我的意思:

#include <stdio.h>

int sum(int a, int b,int c)
{
        return(a+b+c);
}

int media(int a, int b,int c)
{
        int total;
        total = a + b + c;
        return (total/3);

}

int main ()
{
        int num1,num2,num3;
        char keypress[1];

        num1 = 5;
        num2 = 10;
        num3 = 15;

        printf ("\nCalling sum function\n");
        sum(num1,num2,num3);
        printf ("\nWaiting a keypress to call media function\n");
        scanf ("%c",keypress);
        media(num1,num2,num3);
        printf ("\nWaiting a keypress to end\n");
        scanf ("%c",keypress);
        return(0);
}

3 个答案:

答案 0 :(得分:2)

  在调用sum函数之后

你的问题是你从未真正停止过sum函数的 。在打印之后你停止了它即将调用它,然后你执行了一些指令,但是你实际上从未将放在中(它需要一些指令来准备参数,还有一个要实际调用,还有更多内容来设置框架。)

您应首先在summedia内设置断点,然后在遇到这些断点时执行info frame。您会注意到断点在函数开头之后(即在函数序言之后)设置了一些指令。跳过的指令正是设置新帧的指令。

在了解其工作原理后,您应该逐步使用stepnext命令。

之后,您可以逐渐使用disasstepinexti命令。

答案 1 :(得分:1)

根据我对你的散文的解释,你对叠加帧的理解略有不同。你是正确的,当一个函数被调用时,创建了一个堆栈框架,但是,你所缺少的是当一个函数返回时,会弹出堆栈框架。堆栈处于与函数开始执行之前相同的状态,除了程序计数器包含刚刚完成执行的函数之后的语句的第一条指令的地址。因此,您不应期望在主执行中的两个函数之后看到3个堆栈帧。您只会看到一个,因为您只有一帧深入main()

对于gdb会话,正如@Employed俄罗斯指出的那样,在打印堆栈帧信息时,你从未真正进入任何函数。

答案 2 :(得分:0)

感谢所有帮助过我的人。下面是gdb会话,显示堆栈帧已更改。

首先我重新编译了C代码:gcc -ggdb stack.c -o stack.bin

gdb stack.bin (gdb)休息时间 (gdb)开始 (gdb)信息框架

堆栈级别0,帧位于0x7fffffffe1a0:  rip = 0x400653 in main(stack.c:26);保存了rip 0x7ffff7a6fead  源语言c。  Arglist位于0x7fffffffe190,args:  当地人在0x7fffffffe190,前一帧的sp是0x7fffffffe1a0  保存的寄存器:   rbp在0x7fffffffe190,rip在0x7fffffffe198

(gdb)继续 仍在进行中。

调用和函数

在stack.c:6处断点1,sum(a = 5,b = 10,c = 15) 总计6 = a + b + c;

(gdb)信息框架 堆栈级别0,帧位于0x7fffffffe180:  rip = 0x4005dd in sum(stack.c:6);保存了rip 0x400684  由帧在0x7fffffffe1a0调用  源语言c。  Arglist位于0x7fffffffe170,args:a = 5,b = 10,c = 15  位于0x7fffffffe170的本地,前一帧的sp是0x7fffffffe180  保存的寄存器:   rbp在0x7fffffffe170,rip在0x7fffffffe178

现在,我将搜索/了解有关输出中信息的更多信息。