3

我试图分析为什么一个(相当大的)程序段错误。如果程序崩溃,它会将核心转储写入 /tmp,我尝试使用 gdb 进行分析。但是,gdb 给了我以下错误:

Reading symbols from /home/user/Executable...Dwarf Error: 
wrong version in compilation unit header (is 4, should be 2) 
[in module /home/user/Executable]

我搜索了一下,发现了 stackoverflow 上的一个线程,作者认为这是用不同的-g标志编译部分代码(恰好是他/她正在使用的库)的结果。

我已经检查了我的可执行文件(C++)和我在我的程序中使用的库(C)上的编译单元的版本

readelf --debug-dump=info Executable | grep -A 2 'Compilation Unit @'

显然,可执行文件到处都有版本 4,而库的版本是 2。我想知道是否有可能解决这个问题以及如何解决?我也很好奇这个问题实际上是如何首先出现的(通过 -g 标志玩弄调试级别根本没有帮助)。

TIA

4

3 回答 3

6

生成单个目标文件 (.o) 的输入集称为编译单元;有关更多信息,请参阅维基百科。为方便起见,“编译单元”通常缩写为“CU”。

编译带有调试信息的 CU 时,每个 CU 都有一个以 CU 头开始的调试信息部分;此标头包含版本号。此调试信息采用称为DWARF的格式。

随着时间的推移,DWARF 标准不断发展。对于每个主要版本,版本号都已更改。这确保了当 DWARF 生产者(例如,编译器)创建调试信息时,DWARF 消费者(例如,调试器)知道会发生什么。

当 gdb 抱怨 CU 的版本时,它实际上是在抱怨 DWARF CU 标头中的版本号。

为了避免这个问题,正如您所发现的,您必须确保您的整个软件开发工具链(编译器、链接器、调试器)能够“说出”相同的 DWARF 版本。您编译最新版 gdb 的解决方案是正确的。

于 2013-07-30T22:30:33.653 回答
4

来自GCC 4.8 发行说明

在 GCC 4.8 之前,使用的默认版本是 DWARF2。要使 GCC 4.8 生成较旧的 DWARF 版本,请使用 -g 和 -gdwarf-2 或 -gdwarf-3

就我而言,添加

-gdwarf-2 -gstrict-dwarf

使旧的调试器再次工作。不过,我同意在大多数情况下使用更新的 GDB 版本是最好的解决方案。

于 2013-11-26T13:50:30.577 回答
1

我已经用 g++(而不是 gcc)编译了库,从而得到了所需的编译单元。但是,这仍然导致 gdb 抛出 DWARF 错误,所以我在机器上编译了最新版本的 gdb,现在终于可以使用了。

于 2013-07-30T20:31:42.647 回答