计算机 · 2021年5月23日 0

gdb笔记

对于调试程序、根据coredump文件查找崩溃原因,gdb是最基本、最重要的工具。因此这里总结下gdb的基本使用方法。

使用gdb查看stl数据结构

在gdb调试或者查看coredump文件时,经常会遇到无法随心所欲查看stl对象的情况,你明明知道你所关心的数据就存在这个stl map、set、vector里面,可是gdb却无法帮你以合适的方式把这些对象的内容展示出来。这个时候我们就需要配置好我们的gdb,使它能够做到这一点。

适用于libstdc++的pretty printers

根据这个gdb wiki,把这个gdb-stl-views的脚本给搞到.gdbinit这个文件里,就可以辅助你查看libstdc++里的stl对象了。或者不弄到.gdbinit里,在启动gdb后,再执行source <path-to-gdb-stl-views-script>命令也行。

适用于libc++的pretty printers

一个是llvm官网上推荐的,亲测有效,但是unordered_map并不正常工作,还得需要按照最新的stl头文件去修改下这个脚本才行。
一个是某个不认识的大佬的作品,看着挺好,不过我用的时候貌似有点问题,可能stl版本对不上,没仔细查证。是作者的相关博客文章。

总而言之,上面这几个pretty printers可以work,但是并不完美,只要你有耐心去看stl头文件对这些对象的定义,动手调一调这些pretty printers的i脚本,最终应该都能够成功地查看内存中的这些stl对象的。

使用gdb调查程序崩溃原因

设置生成core文件

gdb常用命令

  • 在gdb连接到进程的时候,想生成core文件
  generate-core-file

或者

  gcore

会生成名为core.<pid>的core文件。

  • 打印制定地址的内存
    https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html
    比如buf是一个char*指针,想打印这个指针指向的10个字节:
  x/10ub buf
  • 设置带条件判断的断点
    https://stackoverflow.com/questions/14390256/gdb-break-if-variable-equal-value
  break iter.c:6 if i == 5
  • 设置加载共享库的路径
    https://visualgdb.com/gdbreference/commands/set_solib-search-path
  set solib-search-path [Directories]
  show solib-search-path
  • gdb中显示函数参数var和var@entry的区别

https://stackoverflow.com/questions/19386073/difference-between-this-and-thisentry#:~:text=The %40entry form refers to,onlinedocs%2Fgdb%2FVariables.html

var显示的是现在该变量的值;var@entry显示的是进入该函数的时候这个变量的值;因为var的值可能和进入函数时的值不一样,所以需要分别显示这两个值;
var@entry需要dwarf-2的debug信息才能显示;https://sourceware.org/gdb/onlinedocs/gdb/Print-Settings.html#set-print-entry_002dvalues

  • gdb反向执行

https://sourceware.org/gdb/onlinedocs/gdb/Reverse-Execution.html#Reverse-Execution

在某些平台上gdb居然支持反向执行,用于回滚程序状态。前提是需要预先执行record或者record btrace命令。