g++ 和 gdb 问题:未找到共享库的调试符号

g++ 和 gdb 问题:未找到共享库的调试符号

我正在将大量应用程序和库从 Debian 7 移植到 Ubuntu 16.04。这是一个 GNU autotools 项目,因此涉及 libtool。gdb 无法找到大多数共享库的符号,即使我使用以前一直有效的选项进行构建。我想知道是否有其他人遇到过这个问题,如果遇到过,他们可能会有什么建议。

我使用的 gdb 版本 Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1。

我正在使用 -g O0 和其他编译器选项进行编译。在构建 12 个库时,这些选项始终被使用。其中只有一个库在构建过程中带有调试符号。我们将它指定为 libA。(在下面的讨论中,只是项目路径的替代。)

省去许多 -I 指令,正在使用的选项是:

-g -O0 -Wconversion -Woverloaded-virtual -Wall -Werror -Wreturn-type - 
Wformat -Wparentheses -Wswitch -Wno-deprecated -Wsign-compare -fno- 
strict-aliasing -Wunused -D__STDC_LIMIT_MACROS -MT MyModule.lo -MD -MP 
-MF .deps/MyModule.Tpo -fPIC -DPIC -o .libs/MyModule.o

当我使用 gdb、文件和其他实用程序查看 libA 时,它看起来很好。

u16dev01:(18:01:32):file libA.so.0.0.0                 ~/dev/product- 
<path>lib/liba/.libs
libA.so.0.0.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), 
dynamically linked, 
BuildID[sha1]=14dc765142914be4c32a07eaa1683b5b2a2f6dae, not stripped

目标文件如下所示:

u16dev01:(18:01:43):file AModule1.o                          
<path>/lib/liba/.libs
AModule1.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not 
stripped

如果我用 gdb 打开共享库,就会得到符号,并且可以列出代码。如果我用 gdb 打开其任何 .o 文件,就会得到符号,并且可以列出代码。

在剩余的 11 个中,文件命令报告两个是 SYSV,另外 9 个是 GNU/Linux,例如:

u16dev01:(18:08:34):file libD.so.0.0.0                      
~/<path>/lib/.libs
libD.so.0.0.0: ELF 64-bit LSB shared object, x86-64, 
version 1 (GNU/Linux), dynamically linked, 
BuildID[sha1]=059733fbc888c3dce86eae21984ea82cddc5b0e9, not stripped

当我打开此库或其任何 .o 文件时,gdb 看不到任何符号。file 命令还报告 .o 文件的 GNU/Linux。没有符号。

有两个库将报告归档为 SYSV。它们的 .o 文件也缺少调试信息,库也是如此。

我重命名了 strip 程序,以排除 Makefile 运行 strip 的可能性,尽管仔细搜索编译器输出后我发现事实并非如此。因此,这不是库构建后符号被剥离的情况。

我尝试使用项目的编译器选项构建一个小测试库。它构建了一个 SYSV 库,并且 gdb 可以很好地加载调试符号。

当 gdb 无法加载符号时,objdump -g 输出会很稀疏。

几天来,我和我的几位同事一直在思考这个问题。为什么构建过程只为其中一个库生成可用的符号?该库没有什么特别之处。为什么其余 11 个库中有 9 个报告为 GNU/Linux,而 2 个报告为 SYSV?为什么这两个库也没有符号?

任何想法都将不胜感激。

答案1

问题最终被追溯到一个遗留的自定义 m4 宏。它无法检测到库包,并破坏了它对写入 Makefile.in 的包含路径变量的贡献。结果是 -I 在许多 -I 指令序列中没有路径。奇怪的是,这没有产生错误......但它似乎确实导致紧随其后的 -g 选项被“吞没”。(结果是一长串以“-I -g”结尾的 -I 路径。这似乎阻止了 g++ 处理 -g 选项。)

纠正错误的 m4 宏以生成非空且有效的包含文件路径可以解决问题。

答案2

您需要在编译命令中使用 -g。请参阅 gcc 手册页中标题为“程序调试选项”的部分。与 -O 选项一起使用时需要注意一些事项。

相关内容