GDB不显示剥离核心文件的符号,即使给出了非剥离版本



我通过经典的configure、make、make install构建了这个程序。几个月后,该程序崩溃了。我仍然有构建目录,源代码和未剥离的可执行文件都位于该目录中。从那里,我这样称呼gdb:

530-north:courier$ gdb -q --core /tmp/core_epoch=1667475742_pid=23653_file=!usr!local!libexec!courier!courierd courierd
Reading symbols from courierd...
[New LWP 23653]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/usr/local/libexec/courier/courierd'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000561e841e5afd in msgq::completed(drvinfo&, unsigned long) ()
(gdb) info args
No symbol table info available.

使用bt,我可以看到两个函数之间的调用序列很长:

#0  0x0000561e841e5afd in msgq::completed(drvinfo&, unsigned long) ()
#1  0x0000561e841e609a in msgq::startdelivery(drvinfo*, delinfo*) ()
#2  0x0000561e841e5bd8 in msgq::completed(drvinfo&, unsigned long) ()
#3  0x0000561e841e609a in msgq::startdelivery(drvinfo*, delinfo*) ()
#4  0x0000561e841e5bd8 in msgq::completed(drvinfo&, unsigned long) ()
...
#204 0x0000561e841e5a17 in msgq::completed(drvinfo&, unsigned long) ()
#205 0x0000561e841e609a in msgq::startdelivery(drvinfo*, delinfo*) ()
#206 0x0000561e841e5a17 in msgq::completed(drvinfo&, unsigned long) ()
#207 0x0000561e841e70fe in courierbmain() ()
#208 0x0000561e841dd030 in main ()

每两次调用都会将堆栈提前0x110,总计约27Kb,这比正在运行的进程分配的132Kb堆栈要少得多,所以这不是堆栈溢出。SIGSEGV可以来自空指针或其他类型。gdb为什么不指出这一点?这是GNU gdb(Debian 10.1-1.7(10.1.90.20210103-git,BTW.

如果省略gdb的最后一个参数,bt就不会显示函数名。我把汇编搞砸了吗?在config.log上,我看到我有'CFLAGS= -march=nocona -O2 -g' 'LDFLAGS= -march=nocona -O2' 'CXXFLAGS= -march=nocona -O2 -std=c++11'。源文件是C++。也许我错过了一些-g?然而,有一些符号。。。

为什么gdb不指向它?

因为您没有使用适当的调试信息编译程序。

您必须在程序集级别调试此崩溃。从disasemble $pcinfo registers开始。

源文件是C++。也许我错过了一些-gs?

是:您的CXXFLAGS没有-g

然而,有些符号是存在的。。。

在UNIX系统(与Windows不同(上,即使没有-g,也会出现函数名(符号((默认情况下(。这里没有矛盾。

更新:

但是,如果我不将未剥离的文件作为参数传递,则不会显示函数名。

是:strip删除符号调试信息。

你可以通过使用一个琐碎的测试来观察这一点:

// t.cc
#include <cstdlib>
struct S {
void fn() { abort(); }
};
int main()
{
S().fn();
}

首先,让我们看看当二进制文件被正确构建用于调试时它是如何工作的:

g++ -g t.cc -o a.out && strip ./a.out -o a.out.stripped &&
./a.out.stripped; gdb -q --batch -ex where ./a.out core
Aborted (core dumped)
...
warning: core file may not match specified executable file.
[New LWP 476070]
Core was generated by `./a.out.stripped'.
Program terminated with signal SIGABRT, Aborted.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007f12444895df in __pthread_kill_internal (signo=<optimized out>, threadid=<optimized out>) at ./nptl/pthread_kill.c:89
#2  __GI___pthread_kill (threadid=<optimized out>, signo=<optimized out>) at ./nptl/pthread_kill.c:89
#3  0x00007f12445f5e70 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00007f1244428469 in __GI_abort () at ./stdlib/abort.c:79
#5  0x000055de28a24165 in S::fn (this=0x7ffcd0d1d80f) at t.cc:4
#6  0x000055de28a2414d in main () at t.cc:9

注意文件/行信息和函数名称的存在。如果我们使用剥离版本,两者都不存在:

ore was generated by `./a.out.stripped'.
Program terminated with signal SIGABRT, Aborted.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007f12444895df in __pthread_kill_internal (signo=<optimized out>, threadid=<optimized out>) at ./nptl/pthread_kill.c:89
#2  __GI___pthread_kill (threadid=<optimized out>, signo=<optimized out>) at ./nptl/pthread_kill.c:89
#3  0x00007f12445f5e70 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00007f1244428469 in __GI_abort () at ./stdlib/abort.c:79
#5  0x000055de28a24165 in ?? ()
#6  0x000055de28a2414d in ?? ()
#7  0x00007f124442920a in __libc_start_call_main (main=main@entry=0x55de28a24139, argc=argc@entry=1, argv=argv@entry=0x7ffcd0d1d928) at ../sysdeps/nptl/libc_start_call_main.h:58
#8  0x00007f12444292bc in __libc_start_main_impl (main=0x55de28a24139, argc=1, argv=0x7ffcd0d1d928, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffcd0d1d918) at ../csu/libc-start.c:389
#9  0x000055de28a24071 in ?? ()

现在让我们重复错误地构建的二进制文件(这就是您所拥有的(:

g++ t.cc -o b.out && strip ./b.out -o b.out.stripped &&
./b.out.stripped; gdb -q --batch -ex where ./b.out core
Aborted (core dumped)
...
warning: core file may not match specified executable file.
[New LWP 478614]
Core was generated by `./b.out.stripped'.
Program terminated with signal SIGABRT, Aborted.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007f21a0a895df in __pthread_kill_internal (signo=<optimized out>, threadid=<optimized out>) at ./nptl/pthread_kill.c:89
#2  __GI___pthread_kill (threadid=<optimized out>, signo=<optimized out>) at ./nptl/pthread_kill.c:89
#3  0x00007f21a0bf5e70 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00007f21a0a28469 in __GI_abort () at ./stdlib/abort.c:79
#5  0x000056049b052165 in S::fn() ()
#6  0x000056049b05214d in main ()

注意存在函数名(S::fn()main(,但缺少文件/行/参数信息。这与您观察到的结果相匹配。

如果您再次使用b.out.stripped,您将获得与上次使用a.out.stripped运行时相同的结果:

Core was generated by `./b.out.stripped'.
Program terminated with signal SIGABRT, Aborted.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007f21a0a895df in __pthread_kill_internal (signo=<optimized out>, threadid=<optimized out>) at ./nptl/pthread_kill.c:89
#2  __GI___pthread_kill (threadid=<optimized out>, signo=<optimized out>) at ./nptl/pthread_kill.c:89
#3  0x00007f21a0bf5e70 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00007f21a0a28469 in __GI_abort () at ./stdlib/abort.c:79
#5  0x000056049b052165 in ?? ()
#6  0x000056049b05214d in ?? ()
#7  0x00007f21a0a2920a in __libc_start_call_main (main=main@entry=0x56049b052139, argc=argc@entry=1, argv=argv@entry=0x7fff3554bc78) at ../sysdeps/nptl/libc_start_call_main.h:58
#8  0x00007f21a0a292bc in __libc_start_main_impl (main=0x56049b052139, argc=1, argv=0x7fff3554bc78, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff3554bc68) at ../csu/libc-start.c:389
#9  0x000056049b052071 in ?? ()

此外,readelf-debug-dump=info-courierd显示了许多版本4的内容。

是的,如果运行readelf --debug-dump b.out可以观察到来自crt0.ocrtbegin.o等的许多DWARF4内容(取决于GCC和GLIBC的构建方式(。

如果链接了.c文件,这些文件也将包含DWARF4调试信息,因为CFLAGS包含-g

但是,无论msgq::completed定义在哪里,DWARF4内容都不会来自哪里。

最新更新