当前位置:C++技术网 > 精选软件 > Linux使用coredump文件调试系列:3 使用GDB调试coredump

Linux使用coredump文件调试系列:3 使用GDB调试coredump

更新时间:2018-12-05 17:43:15浏览次数:1+次

    本文的目的不是教你如何使用GDB指令调试,而是告诉你如何去用gdb加载coredump进入调试,然后看看崩溃进程的堆栈。主要是先将coredump玩转起来。我们在《Linux使用coredump文件调试系列1-设置生成coredump文件》中已经讲解了如何去设置生成coredump文件,设置好之后我们在《Linux使用coredump文件调试系列2-编译生成会产生coredump文件的程序并测试》一文中演示了编译产生coredump的方法并测试产生coredump文件。那么我们这里就要开始进入调试coredump文件的环节了。
1.最简单的方式
    直接用gdb加载core文件,命令如下:

gdb /data/corefile/core-test-singal\(11\)-pid\(26676\)-ts\(1544000344\)
    然后会出现以下结果:
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
[New Thread 26676]
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
#0 0x00007f9941591ac0 in ?? ()
"/data/corefile/core-test-singal(11)-pid(26676)-ts(1544000344)" is a core file.
Please specify an executable to debug.
(gdb)
    这样就已经带着coredump文件进入到了GDB环境,可以在(gdb)后面输入命令来调试。我们这里只说一个命令,那就是bt即back trace的缩写,也就是查看程序崩溃时的堆栈情况。输入bt之后,显示下面的结果:
(gdb) bt
#0 0x00007f29db527ac0 in ?? ()
#1 0x0000000000000032 in ?? ()
#2 0x00007f29db85ff60 in ?? ()
#3 0x0000000000000400 in ?? ()
#4 0x00007f29db537176 in ?? ()
#5 0x000000000000000b in ?? ()
#6 0x0000000000000004 in ?? ()
#7 0x0000000000000001 in ?? ()
#8 0x0000000000002190 in ?? ()
#9 0x0000000000000005 in ?? ()
#10 0x0000000000008801 in ?? ()
#11 0x0000000000000000 in ?? ()
(gdb)
    可以显示堆栈,但是每一层只有一个地址,调用的函数名称都是问号。
    显然这个调试方法不太好,简单但有问题。我们换第二个。输入Ctrl+Z退出GDB环境。
2.先用gdb启动程序,然后再挂载coredump文件
    这样一来,我们可以将程序的情况先加载到gdb环境里,然后再将coredump加载到gdb里,这样可以读取程序的调试信息,然后结合coredump文件,这样显示的信息会更多些。
    gdb加载程序命令如下:
gdb ./test
    结果如下:
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /tmp/test...done.
(gdb)
    可以看到gdb从test程序里读取了symbols即符号,也就是程序的相关信息。现在再来加载coredump文件。输入命令如下:
core-file /data/corefile/core-test-singal(11)-pid(22704)-ts(1543995880)
    结果如下:
[New Thread 22704]
Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/lib64/libc-2.12.so.debug...done.
done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib64/ld-2.12.so.debug...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
#0 0x00007f29db527ac0 in _IO_vfscanf_internal (s=<value optimized out>, format=0x40068e "", argptr=0x7ffc2054e220, errp=0x0)
at vfscanf.c:1772
1772 *ARG (unsigned int *) = (unsigned int) num.ul;
(gdb)
    结果已经显示了更多的信息了。因为相比之前来讲,这里已经显示了_IO_vfscanf_internal ,我们可以判断出来,出问题是scanf。但是我们程序可能有很多地方有scanf,所以要准确锁定位置,我们需要把堆栈打印出来。还是输入bt命令。结果如下:
(gdb) bt
#0 0x00007f29db527ac0 in _IO_vfscanf_internal (s=<value optimized out>, format=0x40068e "", argptr=0x7ffc2054e220, errp=0x0)
at vfscanf.c:1772
#1 0x00007f29db5352bd in __isoc99_scanf (format=<value optimized out>) at isoc99_scanf.c:37
#2 0x000000000040056c in b ()
#3 0x000000000040057c in go ()
#4 0x000000000040058c in main ()
    到此,我们看到了一个完整的堆栈。最底下的是最先执行的,这个崩溃位置为:main->go->b->scanf,可以回看第二篇文章的代码,定位非常准确。
    当然,还有人说他这么做,就是看不到每一层的函数名,怎么办?这是因为大家的环境有差异。实际上我第一次使用时也会出现怎么弄也显示不出来,后来发现是少了些东西,安装之后,就好了。限于篇幅,后续的处理,就在下一篇讲解了。
    在这一篇的讲解中,你能看到堆栈,就已经完成了目标了。