关闭

gdb调试--堆栈相关

标签: gdb调试linux
470人阅读 评论(0) 收藏 举报
分类:

GDB调试程序最常用的莫过于使用bt命令查看发生问题时的调用栈了。显示的堆栈信息依次是从最底层到最上层的一个被调用关系。

那这些堆栈信息是如何而来的?函数在调用的时候会自动的将一些信息压栈。以x86架构下为情况说明,首先压入的是参数,在有多个多个参数的情况下,从右往左依次压入;然后是调用函数的返回地址;接着是压调用函数的栈帧的帧指针ebp(或者rsp);再下来就是被调用函数的局部变量了。

 

图1

下面以上图中所示代码为例看下是如何压栈的?

在第13行打断点,运行到此断点的情况如下:

 

 

图2

红色框部分就是建立栈帧的过程,将rbp寄存器压栈,并将rsp的值赋给rbp,正如用i reg命令查看寄存器看到rbp等于rsp,这时候栈帧为空,栈底部等于顶部位置。

 

蓝色框部分是准备将func的参数压栈,在x86架构下传参是通过压栈的方式(ARM下面是通过寄存器的方式传递参数的,当然x86下面也是可以通过__attribute__((regparm(n)))的方式,来用寄存器传参的,后面会讲)。

rsi/esi寄存器用来传递第二个参数,rdi/edi寄存器用来传递第一个参数。图2中就是讲第一个参数1赋给edi,第二个参数赋给esi。

 

按s进入func函数

 

图3

绿色框部分是func函数建立堆栈的一个过程。看下此时寄存器的值是什么情况。

 

图4

 

Func函数栈帧的栈顶部在rsp指向的0x7fffffffe5d0位置处,栈底部在rbp指向的0x7fffffffe5f0位置处。此时堆栈的大致情况如下图5所示。图3中红色框部分就是将参数1和2压栈的指令,蓝色框部分就是将局部变量0和1压栈的指令。

 

图5

用”x 地址”方式可以查看堆栈各个位置的信息,以作验证。

 

在函数调用的过程中建立栈帧会消耗一定的时间,例如在频繁调用库函数的场景下,我们是否可以不建立栈帧,来节省这一时间呢?在编译的时候带上-fomit-frame-pointer选项,就能够做到。

 

 

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18270次
    • 积分:476
    • 等级:
    • 排名:千里之外
    • 原创:30篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类