美文网首页
使用 gdb 恢复堆栈信息

使用 gdb 恢复堆栈信息

作者: 让笑意折了枝 | 来源:发表于2015-11-08 23:06 被阅读2204次

用 C/C++ 编写的程序, 如果遇到 Segmentation Fault 则可以通过生成 coredump 来进行调试, 根据记录的信息定位到出错代码行. 但很多时候可能用 gdb 打开 coredump 文件查看堆栈时, 却出现一堆问号, 无法直接定位到出错代码行. 本文介绍另一种方法来还原错乱的堆栈信息.

例如, 下图是 coredump 后用 gdb 看到的堆栈信息, 可以看到这些代码都是系统依赖库中的函数信息, 如果太多地方调用这些库接口, 就很难定位到问题所在. 下图中应是在调用字符串转数字接口时出错.

coredump 堆栈信息示例

上图中仍无法定位到代码中的具体某一行. 不过寄存器 ebp 中存放了函数帧指针, 这就提供了一个追踪栈信息的线索. 首先将 ebp 的内容打印出来:

寄存器 ebp 的内容

众所周知, 栈即函数的调用栈布局. 每次函数调用, 就会将当前函数的地址及局部变量压入栈顶. 这些调用信息是以一个单向链表来组织的, 上面看到的 ebp 内容就是这个链表的 head 指针. 那么打印出 ebp 内容 0x9e76f354 指针所指内容如下:

寄存器 ebp 内容所指向的区域信息

与 head 节点一样, 第一个节点的最低 4 个字节存储的是下一链表节点位置的指针, 紧随其后的 4 个字节是该层调用的返回地址, 查看其内容如下:

第一个节点调用的返回地址

可以看到, 栈顶的函数地址是与 bt 命令打印的信息一致, 依次打印出该链表上节点信息如下:

链表各节点信息

上述信息已经基本还原了 bt 所能打印出来信息, 上图中后面的节点可以看出导致 coredump 的代码位置, 是在 TtcThmDescOper::tbThmDesc_get 函数中一次 atoll 调用时导致.

以上就是在 bt 无法打印堆栈内容时, 采用另一种方式还原函数调用层级的方式, 希望能对大家定位问题有一定帮助. 另外需要提醒大家的是, 在 64 位系统中, 寄存器 esp 变成了 rsp, 寄存器 ebp 变成了 rbp, 寄存器 ip 变成了 rip. 而在 arm 平台中, 寄存器 ebp 则变成了 fp.

参考文献

  1. gdb 如何还原错乱的堆栈信息 http://hobodong.me/post/81/gdb/

相关文章

  • 使用 gdb 恢复堆栈信息

    用 C/C++ 编写的程序, 如果遇到 Segmentation Fault 则可以通过生成 coredump 来...

  • 各种linux命令(pwn)

    (gdb)bt //查看函数堆栈 (gdb)info break ...

  • Linux调试-GDB

    启动GDB调试 在使用GDB之前,编译出带调试信息的程序,调试信息中包含了函数和变量所在文件和行号信息,通过gcc...

  • gdb调试

    gcc 需要使用gdb调试时需要加-g选项 gdb选项 -q 不显示版本信息 CoreFile CoreFile可...

  • 2019-04-15命令重装tcp/ip

    重新安装TCP/IP以使TCP/IP堆栈恢复为原始状态。可以使用NetShell实用程序重置TCP/IP堆栈,使其...

  • gdb打印所有堆栈

    threadapplyallbt

  • Throwable的使用

    1 取出Throwable的堆栈信息 使用Throwable一个很大的好处在于,他能保存他被实例化的方法的堆栈信息...

  • 死锁问题排查

    首先使用jps查询进程ID然后使用jstack和进程ID查询堆栈日志信息。

  • zerolog日志高级使用

    使用github.com/pkg/errors打印详细的堆栈信息,输出非常友好。 设置堆栈打印详细调用过程 输出详...

  • 如何在Docker内部使用gdb调试器

    背景 前几天一个小伙伴发邮件问我,他在docker内部使用gdb调试时刻遇到了gdb如下报错信息ptrace:Op...

网友评论

      本文标题:使用 gdb 恢复堆栈信息

      本文链接:https://www.haomeiwen.com/subject/luachttx.html