您的位置:首页 > 其它

gdb调试需要使用到的一些知识(心得)

2009-05-25 11:01 337 查看
为了更好的使用gdb来调试程序,需要具备一下技能:
gdb的基本调试手段,比如b **.c:fun linenum 设置断点 , next:单步执行, step 单步调试,可以跟踪进函数。注意编译的时候要加上-g选项。
info reg:查看寄存器状态。info locals:查看局部变量 p:打印变量的值 l:显示代码。x:以16进制的方式打印地址中的值。
linux内存分配原理:局部变量放在栈中,栈外向低地址增长,栈内向高地址端增长;malloc的空间在堆上,堆外向高地址端增长,堆内向低地址端增长;代码放在代码段;全局变量和静态放在数据段;未初始化的数据放在bss数据段。linux的32为位线性地址空间4G,从0xbfffffff开始往下是栈,从0x08000000开始往上依次是代码段,已初始化的全局变量和静态变量的数据段,未初始化的全局变量和静态变量的数据段,malloc动态分配的空间。在中间0x40000000往上是linux给共享内存分配的线性地址空间。
程序运行基本入栈原理:首先介绍3个重要的寄存器:%ebp,%esp,%eip。%ebp:存放栈底地址,%esp:存放栈顶地址,%eip:存放下一条要运行的汇编代码的地址。例如:一个func1函数调用一个func2函数,那么call func2之前一般会将func2函数需要使用的参数从右到左依次入栈,然后call func2这条语句会引发以下动作,将call func2的下一条要执行的汇编代码的地址入栈,将%ebp入栈(即func1函数的栈底地址入栈),之后便进入func2函数了,会将他要用到的局部变量和他需要保存的一些寄存器入栈,如果你用gdb跟踪到此处,运行info reg你便可以清楚的看到%eip中存放了一个地址,你如何确认他就是call func2之后要执行的那条语句的地址呢?你运行disassemble func1便可以看到call func2之后运行的汇编代码的地址了,好奇的你如果还想进一步看看栈中是否有之前说的将call func2的下一条要执行的汇编代码的地址入栈,你可以运行x/n %ebp(**表示你希望打印地址之后4n个字节地址中的值。)。一般每个函数推出的时候都会执行ret,目的是为了将此函数的数据退栈,他会做一些准备,首先mov %ebp %esp之后将%ebp中的值(即上一层函数func1的栈底地址)出栈,此时%esp便指向了call func2之后要执行的汇编代码的地址了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: