如何使用gdb和core-dump文件找到这个segmentation fault的原因?(GDB的局限性)

How to find the cause of this segmentation fault using gdb and core-dump file?(Limitation of GDB)

我知道我可以使用核心转储文件找出程序哪里出错了。但是有一些BUG,就是用core文件调试也不知道为什么会出错。所以我想传达的是,gdb和core文件能帮你调试的bug范围是有限的。这有多有限?

比如我写了下面的代码:(libfoo.c)

#include <stdio.h>
#include <stdlib.h>
void foo(void);
int main()
{
    puts("This is a mis-compiled runnable shared library");
    return 0;
}
void foo()
{
    puts("This is the shared function");
}

以下是 makefile : (Makefile)

.PHONY : all clean
all : libfoo.c
    gcc -g -Wall -shared -fPIC -Wl,-soname,$(basename $^).so.1 -o $(basename $^).so.1.0.0 $^; \
#the correct compiling command should be : 
#gcc -g -Wall -shared -fPIC -pie -Wl,--export-dynamic,-soname,$(basename $^).so.1 -o $(basename $^).so.1.0.0 $^; 
    sudo ldconfig $(CURDIR);                        #this will set up soname link     \ 
    ln -s $(basename $^).so.1.0.0 $(basename $^).so #this will set up linker name link;
clean : 
    -rm libfoo.s*; sudo ldconfig;#roll back

当我 运行 它 ./libfoo.so 时,我得到了分段错误,这是因为我以错误的方式编译了 运行nable 共享库。但我想知道到底是什么导致了分段错误。所以我使用了 gdb libfoo.so.1.0.0 corefile,然后是 bt,得到了以下结果:

[xhan@localhost Desktop]$ gdb ./libfoo.so core.8326 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 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 /home/xiaohan/Desktop/libfoo.so.1.0.0...done.

warning: core file may not match specified executable file.
[New LWP 8326]
Core was generated by `./libfoo.so'.
Program terminated with signal 11, Segmentation fault.
#0  0x0000000000000001 in ?? ()
(gdb) bt
#0  0x0000000000000001 in ?? ()
#1  0x00007ffd29cd13b4 in ?? ()
#2  0x0000000000000000 in ?? ()
(gdb) quit

但我仍然不知道是什么导致了分段错误。调试核心文件不能给我任何线索,我的分段错误的原因是我使用了错误的编译命令。

谁能帮我调试一下?或者谁能​​告诉我即使使用 gdb 和核心文件也无法调试的错误范围?仅回答一个问题的答案也将被接受。

谢谢!


我持有的重要假设:

  1. 有些人可能会问我为什么要使共享库 运行可用。我这样做是因为我想编译一个类似于 /lib64/ld-2.17.so.
  2. 的共享库
  3. 当然你不能指望 gdb 告诉你每一个错误的原因。例如,如果你简单地chmod +x nonexecutable和运行它,然后得到一个错误(通常这不会转储核心文件),并尝试用gdb调试它,有点"crazy"。但是,一旦 "executable" 可以加载并在 运行 期间转储核心文件,您可以使用 gdb 对其进行调试,此外,查找有关程序出错原因的线索。然而,在我的问题./libfoo.so中,我完全迷失了。

the scope of the bugs that gdb and core files can help you to debug is limited.

正确:core 转储对几个大的 类 错误几乎没有帮助。最常见的(根据我的经验)是:

  1. 进程启动时发生的问题(例如您展示的示例)。

    GDB需要动态加载器配合,告诉GDB各种ELF镜像在进程space.

    mmap在哪里

    当崩溃发生在动态加载器本身时,或者在动态加载器有机会告诉 GDB 东西在哪里之前,你会得到一个非常混乱的画面。

  2. 各种堆损坏错误。

    通常你可以判断出问题很可能是堆损坏(例如 mallocfree 内的任何崩溃通常是一个标志),但这告诉你 很少关于问题的根本原因。

    幸运的是,Valgrind 和 Address Sanitizer 等工具通常可以直接指出问题所在。

  3. 各种堆栈溢出错误。

    GDB 使用当前堆栈的内容告诉您如何到达您所在的函数 (backtrace)。

    但是如果你用垃圾覆盖堆栈内存,那么你如何到达你所在位置的记录就会丢失。如果你破坏堆栈,然后使用 "grbage" 函数指针,那么你最终会得到一个核心转储,你无法从中分辨出你在哪里,或者你是如何到达那里的。

  4. 各种 "logical" 个错误。

    例如,假设您有一个树数据结构和一个访问其节点的递归过程。如果你的树不是一棵真正的树,并且里面有一个循环,你的访问过程将 运行 出栈并崩溃。

    但是看着崩溃告诉你什么都没有关于树不再是树而是变成图形的地方。

  5. 数据竞争。

    您可能正在遍历 std::vector 的元素并崩溃。检查向量表明它不再处于有效状态。

    当其他线程修改您下面的向量(或任何其他数据结构)时,经常会发生这种情况。

    同样,崩溃堆栈跟踪很少告诉您错误的实际位置。