如何更改编译单元的版本

How to change the version of a compilation unit?

本文关键字:版本 单元 编译 何更改      更新时间:2023-10-16

我试图分析为什么一个(相当大的)程序会出错。如果程序崩溃,它会向/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

生成单个对象文件(.o)的一组输入称为编译单元;有关更多信息,请参阅维基百科。为了方便起见,"编译单元"通常缩写为"CU"

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

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

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

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

来自GCC 4.8发行说明:

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

在我的情况下,添加

-gdwarf-2 -gstrict-dwarf

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

我用g++(而不是gcc)编译了库,这产生了所需的编译单元。然而,这仍然导致了gdb抛出的DWARF错误,因此我在机器上编译了gdb的最新版本,最终它现在可以工作了。