gdb demangler对加载符号的段错误

时间:2015-01-31 06:47:37

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

最近,我开始使用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等。

对不起,截止日期现在非常严厉,所以一旦有更多的时间。

1 个答案:

答案 0 :(得分:1)

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

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

这就是你所经历的。

去年,有一个补丁用SEGV捕手包裹了对demangler的调用。这样gdb可以至少与demangler bug有点隔离 - 它打印出有问题的符号并尝试进行攻击。

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

另外,请允许我建议点击Gary的错误报告说明:https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c35。也就是说,如果您知道该符号,请提交GCC错误;否则用复制器提交gdb错误,有人会对它进行分类。

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