$ ./crash -p param1 -o param2
Segmentation fault (core dumped)
$ gdb ./crash core
GNU gdb (GDB) 7.1-ubuntu
...
Core was generated by `./crash -p param1 -o param2'. <<<<< See this line shows crash scenario
Program terminated with signal 11, Segmentation fault.
#0 __strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99 ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)
如果要将参数传递给要在gdb中调试的可执行文件,请使用 --args . 例如:
$ gdb --args ./crash -p param1 -o param2
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) r
Starting program: /home/@@@@/crash -p param1 -o param2
Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99 ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
(gdb)
text addr: 0x4007d4
data addr: 0x7ffec6739220
mmap addr: 0x1612010
Segmentation fault (core dumped)
GDB将我们指向了segfault发生的确切行,这是大多数用户在调试时想要的:
gdb -q -nh main.out core
然后:
Reading symbols from main.out...done.
[New LWP 27479]
Core was generated by `./main.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000000000400635 in myfunc (i=1) at main.c:7
7 *(int*)(NULL) = i;
(gdb) bt
#0 0x0000000000400635 in myfunc (i=1) at main.c:7
#1 0x000000000040072b in main (argc=1, argv=0x7ffec6739328) at main.c:28
这直接指向了越野车7号线 .
Binutils analysis
第一:
file core
告诉我们 core 文件实际上是一个ELF文件:
core: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './main.out'
这就是为什么我们能够使用通常的binutils工具更直接地检查它 .
更多格式信息可在以下位置找到:
man 5 core
然后:
readelf -Wa core
给出了一些关于文件结构的提示 . 内存似乎包含在常规程序头中:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NOTE 0x000468 0x0000000000000000 0x0000000000000000 0x000b9c 0x000000 0
LOAD 0x002000 0x0000000000400000 0x0000000000000000 0x001000 0x001000 R E 0x1000
LOAD 0x003000 0x0000000000600000 0x0000000000000000 0x001000 0x001000 R 0x1000
LOAD 0x004000 0x0000000000601000 0x0000000000000000 0x001000 0x001000 RW 0x1000
9 回答
您可以通过多种方式将核心与gdb一起使用,但是将要传递给可执行文件的参数传递给gdb不是使用核心文件的方法 . 这也可能是你遇到这个错误的原因 . 您可以通过以下方式使用核心文件:
gdb <executable> <core-file>
或gdb <executable> -c <core-file>
或使用核心文件时,您不必传递参数 . 崩溃场景显示在gdb中(使用Ubuntu上的gdb版本7.1进行检查) . 例如:
如果要将参数传递给要在gdb中调试的可执行文件,请使用
--args
.例如:
手册页将有助于查看其他gdb选项 .
简单使用GDB,调试coredump文件:
创建“进程”的Coredump文件,作为“core.pid”文件 . 进入gdb-prompt后,(在执行上述命令时),键入;
这将为您提供堆栈信息,您可以在其中分析崩溃/故障的原因 . Other command, 出于同样的目的;
这与上面相同 . 按照惯例,它列出了整个堆栈信息(最终导致崩溃位置) .
跳过参数,gdb不需要它们:
从RMS's gdb Debugger Tutorial:
确保您的文件确实是
core
图像 - 使用file
进行检查 .稍微不同的方法将允许您完全跳过GDB . 如果你想要的只是一个回溯,那么linux特定的实用程序'catchsegv'将捕获SIGSEGV并显示一个回溯 .
无论可执行文件是否有参数,在任何带有生成的核心文件的二进制文件上运行GDB语法如下 .
让我以下面的例子来进一步理解 .
从上面的输出中,你可以猜出一些关于核心的东西,无论是NULL访问还是SIGABORT等 .
这些数字#0到#10是GDB的堆栈帧 . 这些堆栈帧不是您的二进制文件 . 如果您怀疑有任何错误,请在上述0-10帧中选择该帧
现在查看有关它的更多详细信息:
要进一步调查问题,您可以在此时打印可疑变量值 .
objdump + gdb minimal runnable example
TL; DR:
objdump -s core
转储内存GDB找到失败的行,前面提到过:How to analyze a program's core dump file with gdb?
现在进行完整的教育测试设置:
main.c中
编译并运行以生成核心:
输出:
GDB将我们指向了segfault发生的确切行,这是大多数用户在调试时想要的:
然后:
这直接指向了越野车7号线 .
Binutils analysis
第一:
告诉我们
core
文件实际上是一个ELF文件:这就是为什么我们能够使用通常的binutils工具更直接地检查它 .
更多格式信息可在以下位置找到:
然后:
给出了一些关于文件结构的提示 . 内存似乎包含在常规程序头中:
并且在备注区域中存在更多元数据 . 值得注意的是,我猜PC必须在那里(TODO确认):
objdump
可以轻松地转储所有内存:其中包含:
它与我们运行中的stdout值完全匹配 .
在Ubuntu 16.04 amd64,GCC 6.4.0,binutils 2.26.1中测试 .
您可以使用“gdb”命令分析核心转储文件 .
谢谢 .
只需键入命令
要么
无需提供任何命令行争论 . 由于早期练习而生成的代码转储 .