【问题标题】:gdb demangler segfault on loading symbolsgdb demangler 加载符号时的段错误
【发布时间】:2015-01-31 06:47:36
【问题描述】:

最近,我开始在使用 GDB 调试我的产品时遇到问题。 我找到了问题的根源,但还没有解决方法。

我的代码是用 C++11 编写的,并大量使用元编程。 为了捕捉和修复可能的崩溃,它使用调试信息进行编译,用于对 SIGSEGV 处理程序进行解组。

扩展项目使一些元组变得相当大。

我将问题缩小到:取消注释一个元组中的一种类型,并在加载符号时在 gdb 中捕获 SegFault。

谷歌搜索这似乎是一项乏味的任务。 用 gdb 调试 gdb 也没有带来更多的洞察力。 我发现的唯一东西是similar bug,但该跟踪器声明它在我的 gdb (7.7.1) 版本中已修复并确认已修复

我使用 Ubuntu 14.04 作为开发盒,Centos7 用于生产服务器,这是“gdb --args gdb”的输出:

xxx@xxx$ gdb --args gdb ./epayworker
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gdb...(no debugging symbols found)...done.
(gdb) run
Starting program: /usr/bin/gdb ./epayworker
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./epayworker...
Program received signal SIGSEGV, Segmentation fault.
0x0000000000719da1 in cplus_demangle_print_callback ()
(gdb) bt -25
#0  0x0000000000719da1 in cplus_demangle_print_callback ()
#1  0x0000000000719fb4 in ?? ()
#2  0x000000000071a0c7 in ?? ()
#3  0x000000000071a26e in cplus_demangle_v3 ()
#4  0x000000000070c3c6 in cplus_demangle ()
#5  0x000000000068fdbb in bfd_demangle ()
#6  0x000000000055f269 in symbol_set_names ()
#7  0x00000000005cb985 in prim_record_minimal_symbol_full ()
#8  0x00000000004f82ba in ?? ()
#9  0x00000000004f8b95 in ?? ()
#10 0x000000000056a8d9 in ?? ()
#11 0x000000000056a459 in ?? ()
#12 0x000000000056a9b4 in symbol_file_add ()
#13 0x000000000056aa15 in ?? ()
#14 0x00000000005921be in catch_command_errors_const ()
#15 0x0000000000594da5 in ?? ()
#16 0x000000000059205a in catch_errors ()
#17 0x0000000000595244 in gdb_main ()
#18 0x000000000045391e in main ()
(gdb) 

在这个阶段,我对为我们的生产服务器核心更改编译器并不感到兴奋。对架构造成限制的错误也不是最好的事情。

所以我的问题是: 我是否缺少某种类型的标志来克服 gdb 中的一些内部限制?或者这只是gdb中的一个错误?或者也许我不应该害怕并迁移到更新的编译器版本?

感谢您对我的困惑提供任何帮助。

更新:

这似乎是一个非常糟糕的情况。 最近我一直在玩元组,似乎问题与某些特定符号无关,而是与某种缓冲区溢出有关。 因为来回交换类型、重命名它们、缩小名称长度并没有什么区别,但是在元组中的类型数量达到一定阈值后,就会出现崩溃。

我发现的最大元组类型名长度约为 77600 个字符(再添加一种类型 - gdb 崩溃)

附带说明的是,Netbeans 8.0.2 也存在错误:在具有大名称长度的类型名称的调用堆栈窗口中,经过某个阈值后,它开始进行某种包装,并在其上打印相同类型名称的不同部分同一行的顶部,使其完全不可读。在某个更大的阈值之后,typename 就会消失,使行为空。

我会提交一个错误。 但由于显而易见的原因,我不能向公众发布我的代码。 因此,我将尝试提取造成这种混乱的部分,并用它构建一个测试应用程序。 部分是:用于构建反射的元函数,如meta-for_each等。

抱歉,现在截止日期很紧迫,所以尽快会有更多时间。

【问题讨论】:

  • 最新的 gdb 7.8.2-0ubuntu1 表现相同。
  • 您是否尝试过调试一个使用与目标应用程序相同的工具链构建的简单空应用程序?
  • 对我来说看起来像一个 gdb 错误。也许您可以提交错误报告。

标签: linux c++11 gcc segmentation-fault gdb


【解决方案1】:

demangler,也许有点令人惊讶,是一个复杂的软件。而且,随着 C++ 的发展,修饰方案变得更加复杂,因此拆解器也变得更加复杂。有时会有错误。

现在,通常这没什么大不了的。但是,为了提供良好的用户体验(也部分是由于编译器 DWARF 生成的历史问题),gdb 急切地对符号进行了解码。如果一个这样的符号触发了一个 demangler 错误——繁荣!

这就是你所经历的。

在过去的一年中,一个补丁使用 SEGV 捕手来包装对 demangler 的调用。这样,gdb 至少可以与 demangler 错误隔离一点——它会打印出有问题的符号并尝试继续前进。

您的 gdb 可能已被修补以修复某些特定已知错误的 demangler,但可能还没有 SEGV 捕获补丁。所以我建议你升级gdb。这应该会有所帮助。

另外,我建议您在此处遵循 Gary 的错误报告说明:https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c35。也就是说,如果您知道符号,请提交 GCC 错误;否则将 gdb 错误提交给复制器,然后有人会对其进行分类。

据我所知,对于这个错误没有合理的解决方法。这就是 SEGV 捕手进入的原因。但是有一个不合理的解决方法 - 编辑二进制文件以重命名有问题的符号以避免 demangler 崩溃。但是,实际上,构建自己的 gdb 更简单、更安全。

【讨论】:

  • 感谢您的建议。我稍后会提交一个错误。我还没有找到任何解决我的问题的方法,所以我现在就试试你提到的补丁。我应该保持这个开放,直到我找到解决这个问题的方法?
  • 另外,为了完整起见:即使没有生成调试信息,gdb 也会崩溃。
  • 如果有问题的重整名称出现在 ELF 符号表中(有时称为“链接器符号”或类似名称),那么即使没有调试信息,它仍然会引发崩溃。那是因为 gdb 也会尝试读取链接器符号。
猜你喜欢
  • 2020-10-04
  • 1970-01-01
  • 2020-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多