Linux 如何分析程序';当具有命令行参数时,是否使用GDB创建内核转储文件?

Linux 如何分析程序';当具有命令行参数时,是否使用GDB创建内核转储文件?,linux,debugging,gdb,coredump,Linux,Debugging,Gdb,Coredump,我的程序是这样运行的: exe -p param1 -i param2 -o param3 它崩溃并生成了一个核心转储文件,core.pid 我想通过以下方式分析核心转储文件: gdb ./exe -p param1 -i param2 -o param3 core.pid 但是GDB将EXE文件的参数识别为GDB的输入 在这种情况下,如何分析核心转储文件?只需跳过参数即可。GDB不需要它们: gdb ./exe core.pid 发件人: 确保您的文件确实是一个core图像——使用fil

我的程序是这样运行的:

exe -p param1 -i param2 -o param3
它崩溃并生成了一个核心转储文件,
core.pid

我想通过以下方式分析核心转储文件:

gdb ./exe -p param1 -i param2 -o param3 core.pid
但是GDB将EXE文件的参数识别为GDB的输入


在这种情况下,如何分析核心转储文件?

只需跳过参数即可。GDB不需要它们:

gdb ./exe core.pid
发件人:


确保您的文件确实是一个
core
图像——使用
file

检查它。您可以通过多种方式将core与GDB一起使用,但将要传递给可执行文件的参数传递给GDB并不是使用core文件的方式。这也可能是你出错的原因。您可以通过以下方式使用核心文件:

gdb
gdb-c

gdb <executable>
...
(gdb) core <core-file>

手册页将有助于查看其他GDB选项。

您可以使用“GDB”命令分析核心转储文件


GDB的简单用法,用于调试coredump文件:

gdb <executable_path> <coredump_file_path>
这将为您提供堆栈的信息,您可以在其中分析崩溃/故障的原因。 其他命令,出于相同目的:

...
(gdb) bt full

这与上面相同。按照惯例,它列出了整个堆栈信息(最终导致崩溃位置)。

稍微不同的方法将允许您完全跳过GDB。如果您只需要一个回溯跟踪,Linux特定的实用程序将捕获SIGSEGV并显示一个回溯跟踪。

只需键入以下命令:

$ gdb <Binary> <codeDump>
$gdb

$gdb
$gdb)核心

不需要提供任何命令行参数。由于前面的练习而生成的代码转储。

可执行文件是否有参数并不重要。要在生成核心文件的任何二进制文件上运行GDB,语法如下

Syntax:
gdb <binary name> <generated core file>
Eg:
gdb l3_entity 6290-corefile
从上面的输出中,您可以猜测有关核心的一些信息,例如它是否是空访问、SIGABORT等

这些数字#0到#10是GDB的堆栈帧。这些堆栈帧不是二进制的。在上述0-10帧中,如果您怀疑有任何错误,请选择该帧

(gdb) frame 8
现在,要查看有关它的更多详细信息:

(gdb) list +
为了进一步调查问题,您可以在此时在此处打印可疑变量值

(gdb) print thread_name

objdump
+
gdb
最小可运行示例

TL;博士:

  • GDB可用于查找故障线路,如前所述:
  • 核心文件包含CLI参数,无需再次传递它们
  • objdump-s core
    可用于批量转储内存
现在了解完整的教育考试设置:

main.c

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int myfunc(int i) {
    *(int*)(NULL) = i; /* line 7 */
    return i - 1;
}

int main(int argc, char **argv) {
    /* Setup some memory. */
    char data_ptr[] = "string in data segment";
    char *mmap_ptr;
    char *text_ptr = "string in text segment";
    (void)argv;
    mmap_ptr = (char *)malloc(sizeof(data_ptr) + 1);
    strcpy(mmap_ptr, data_ptr);
    mmap_ptr[10] = 'm';
    mmap_ptr[11] = 'm';
    mmap_ptr[12] = 'a';
    mmap_ptr[13] = 'p';
    printf("text addr: %p\n", text_ptr);
    printf("data addr: %p\n", data_ptr);
    printf("mmap addr: %p\n", mmap_ptr);

    /* Call a function to prepare a stack trace. */
    return myfunc(argc);
}
输出:

text addr: 0x4007d4
data addr: 0x7ffec6739220
mmap addr: 0x1612010
Segmentation fault (core dumped)
GDB为我们指出了分段错误发生的确切位置,这是大多数用户在调试时想要的:

gdb -q -nh main.out core
然后:

它直接把我们引向了四轮马车的7号线

CLI参数存储在核心文件中,无需再次传递

为了回答特定的CLI参数问题,我们发现如果更改CLI参数,例如:

rm -f core
./main.out 1 2
然后,这会反映在前面的bactrace中,而不会对我们的命令进行任何更改:

Reading symbols from main.out...done.
[New LWP 21838]
Core was generated by `./main.out 1 2'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
7           *(int*)(NULL) = i; /* line 7 */
(gdb) bt
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
#1  0x0000564583cf2858 in main (argc=3, argv=0x7ffcca4effa8) at main.c:2
因此,请注意现在如何
argc=3
。因此,这必须意味着核心文件存储该信息。我猜它只是将其存储为
main
的参数,就像存储任何其他函数的参数一样

这是有意义的,如果你认为核心转储必须存储程序的整个内存和登记状态,那么它就有了确定当前堆栈上函数参数值所需的所有信息。 不太明显的是如何检查环境变量:环境变量因此objdump确实包含这些信息,但我不确定如何方便地一次列出所有环境变量,如下所示,但我的测试确实有效:

p __environ[0]
Binutils分析

通过使用binutils工具,如
readelf
objdump
,我们可以批量转储
核心
文件中包含的信息,例如内存状态

它的大部分/全部也必须通过GDB可见,但这些binutils工具提供了一种更大容量的方法,这对于某些用例来说是方便的,而GDB对于更交互式的探索则更方便

第一:

file core
告诉我们
核心文件实际上是一个文件:

这就是为什么我们能够用常用的binutils工具更直接地检查它

快速浏览一下,就会发现实际上有一种ELF类型专门用于它:

Elf32_Ehd.e_type == ET_CORE
有关更多格式信息,请访问:

man 5 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
notes区域中还有一些元数据:

objdump
可以通过以下方式轻松转储所有内存:

objdump -s core
其中包括:

Contents of section load1:

 4007d0 01000200 73747269 6e672069 6e207465  ....string in te
 4007e0 78742073 65676d65 6e740074 65787420  xt segment.text 

Contents of section load15:

 7ffec6739220 73747269 6e672069 6e206461 74612073  string in data s
 7ffec6739230 65676d65 6e740000 00a8677b 9c6778cd  egment....g{.gx.

Contents of section load4:

 1612010 73747269 6e672069 6e206d6d 61702073  string in mmap s
 1612020 65676d65 6e740000 11040000 00000000  egment..........
它与运行中的标准输出值完全匹配


这是在Ubuntu 16.04 amd64、GCC 6.4.0和binutils 2.26.1上测试的。

我只是使用
coredumpctl debug
(在Fedora32上),它给了我一个GDB控制台来调试我最近的核心转储。

但这不起作用。gdb输出警告:核心文件可能与指定的可执行文件不匹配。无法从内存中读取有效的对象文件映像。“核心文件可能与指定的可执行文件不匹配”。在exe生成核心后,您是否修改了它?您是否使用不同的命令行选项重建了它?给GDB一个产生核心的完全相同的二进制是非常重要的。如果你不这样做,你会把垃圾清除掉。还要确保传递给gdb的二进制文件没有被剥离。您可以运行“file”,显示它是否已剥离。您确定您的
exe
不是shell脚本(用于设置某些变量等),例如
firefox
在Linux上?out.txt是可执行文件吗?这似乎是一个误导性的文件扩展名。
rm -f core
./main.out 1 2
Reading symbols from main.out...done.
[New LWP 21838]
Core was generated by `./main.out 1 2'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
7           *(int*)(NULL) = i; /* line 7 */
(gdb) bt
#0  0x0000564583cf2759 in myfunc (i=3) at main.c:7
#1  0x0000564583cf2858 in main (argc=3, argv=0x7ffcca4effa8) at main.c:2
p __environ[0]
file core
core: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './main.out'
Elf32_Ehd.e_type == ET_CORE
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
Displaying notes found at file offset 0x00000468 with length 0x00000b9c:
  Owner                 Data size       Description
  CORE                 0x00000150       NT_PRSTATUS (prstatus structure)
  CORE                 0x00000088       NT_PRPSINFO (prpsinfo structure)
  CORE                 0x00000080       NT_SIGINFO (siginfo_t data)
  CORE                 0x00000130       NT_AUXV (auxiliary vector)
  CORE                 0x00000246       NT_FILE (mapped files)
    Page size: 4096
                 Start                 End         Page Offset
    0x0000000000400000  0x0000000000401000  0x0000000000000000
        /home/ciro/test/main.out
    0x0000000000600000  0x0000000000601000  0x0000000000000000
        /home/ciro/test/main.out
    0x0000000000601000  0x0000000000602000  0x0000000000000001
        /home/ciro/test/main.out
    0x00007f8d939ee000  0x00007f8d93bae000  0x0000000000000000
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93bae000  0x00007f8d93dae000  0x00000000000001c0
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93dae000  0x00007f8d93db2000  0x00000000000001c0
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93db2000  0x00007f8d93db4000  0x00000000000001c4
        /lib/x86_64-linux-gnu/libc-2.23.so
    0x00007f8d93db8000  0x00007f8d93dde000  0x0000000000000000
        /lib/x86_64-linux-gnu/ld-2.23.so
    0x00007f8d93fdd000  0x00007f8d93fde000  0x0000000000000025
        /lib/x86_64-linux-gnu/ld-2.23.so
    0x00007f8d93fde000  0x00007f8d93fdf000  0x0000000000000026
        /lib/x86_64-linux-gnu/ld-2.23.so
  CORE                 0x00000200       NT_FPREGSET (floating point registers)
  LINUX                0x00000340       NT_X86_XSTATE (x86 XSAVE extended state)
objdump -s core
Contents of section load1:

 4007d0 01000200 73747269 6e672069 6e207465  ....string in te
 4007e0 78742073 65676d65 6e740074 65787420  xt segment.text 

Contents of section load15:

 7ffec6739220 73747269 6e672069 6e206461 74612073  string in data s
 7ffec6739230 65676d65 6e740000 00a8677b 9c6778cd  egment....g{.gx.

Contents of section load4:

 1612010 73747269 6e672069 6e206d6d 61702073  string in mmap s
 1612020 65676d65 6e740000 11040000 00000000  egment..........