gcc/g++ 不为变量生成调试符号

Posted

技术标签:

【中文标题】gcc/g++ 不为变量生成调试符号【英文标题】:gcc/g++ not producing debug symbols for variables 【发布时间】:2016-10-21 23:11:13 【问题描述】:

我已经尝试过 gcc 和 g++,它们中的每一个都使用 -g-O0-Og 以及它们的各种组合,甚至是 gcc -g -Og -c main.c -O0 -g -g -g -g。我的变量没有符号。

我用以下代码做了一个简化的测试程序:

#include <stdio.h>

void aFunction()  printf("?\n"); 

int main(int argc, char** argv)

    int intVariable = 0;
    printf("argc = %d, intVariable = %d\n", argc, intVariable);
    return 0;

即使使用 gcc 或 g++ 编译的代码,使用各种 -g/-O0/-Og 方式,也尝试 -c 以确保链接阶段没有将其剥离,仍然,在.o 或 .out 文件我可以看到函数但看不到变量。

我正在检查 nm main.o(或省略 -c 时的 nm a.out)。输出包括aFunctionmain,但不包括argcintVariable

我已经阅读了很多问题/答案/帖子/文章/等。试图弄清楚为什么 gcc/g++ 没有为我的变量生成调试符号,但我无法解决这个问题。大多数来源只提到-g-O0-Og,并避免-s 和编译优化。

我需要在 gdb 中进行调试的符号。如果我做gdb a.out 然后break main,让它运行并中断,然后bt 确认我在mainprint argcprint intVariable 我在当前上下文中得到“无符号”argc“ 。”因为它们的符号不存在。

在 gdb 中运行时,我还收到消息“缺少单独的调试信息,请使用:debuginfo-install glibc-...”我在这里提到它是为了完整性,但我认为这无关紧要,如果我理解的话正确,只有当我想调试到较低级别的 glibc 特定代码时才需要这样做。如果我错了,请纠正我。

这不是我第一次尝试解决此问题,而且这种尝试又浪费了很多时间。如果能正确使用gdb就好了。

如何解决编译代码中缺少符号的问题?

我使用的是 gcc 4.9.2。我已经在几台不同的计算机上测试了几个版本的 Red Hat。我没有能力在工作中更改任何版本或在此处安装任何东西,但我可以在家时尝试不同版本的 gcc 或操作系统。

Chris Dodds 指出,这可能是我的 GDB 版本,而不是我的版本或用法或 GCC。执行gdb --version 会产生以GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6) 开头的输出。

【问题讨论】:

您使用的是什么版本的 gdb? gcc4.9 通常会生成较旧版本的 gdb 无法理解的 dwarf v4 调试符号,但通常您会从 gdb 收到关于无法读取调试符号的错误。 gdb --version 输出:GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6) 版权所有 (C) 2010 Free Software Foundation, Inc. 许可证 GPLv3+:GNU GPL 版本 3 或更高版本(这里有更多不相关的许可证信息)这个 GDB 被配置为“x86_64-redhat-linux-gnu”。 gcc --version 提供4.9.2 这是一个非常古老的 gdb 版本。我已经成功地将 7.8.1 与 gcc 4.9 一起使用。 7.12 似乎是最新的 gdb 版本。 我会看看我是否可以更新 GDB。希望这就是问题的全部。如果/何时(这是一个很大的如果/何时)我会报告我可以让某人更新 GDB。我之前曾要求对其进行更新但没有成功,但由于它现在可能实际上会导致问题,我将尝试将其向上移动。谢谢。 【参考方案1】:

nm 通常不显示调试符号。您可以尝试使用-a--debug-syms 选项来显示它们。

为了更好的显示调试符号,可以试试dwarfdump

最可能的解释是您在可执行文件中获得了调试符号,但 gdb 无法读取它们,因为您的发行版有一个旧(er)版本的 gdb,它不理解由 new(er) 生成的 dwarf 版本) 版本的 gcc。解决方案通常是将 gdb 更新到最新版本(可能需要在某些发行版上从源代码构建)。

【讨论】:

谢谢。我读过的其他一些答案/帖子建议使用nm 来验证符号是否存在,但我没有提到-a/--debug-syms 的要求。所以我刚刚添加了--debug-syms,它显示了更多数据,包括第二列中带有N 的条目,但没有argc/intVariable 的条目。 由于局部变量不在特定地址(它们在寄存器或堆栈帧中),因此它们没有直接的符号。相反, .debug_info 部分包含有关此类符号的信息。使用dwarfdump 实际解码各个调试部分的内容。 那么,您是在暗示这是 GCC 的预期行为,还是 Linux 调试格式,或者您想责备的任何人?我应该不再能够轻松地看到局部变量符号,如果我在 GDB 中运行,我应该不再能够打印局部变量,即使我使用 -g-O0-O0 编译?我假设我正在经历的事情是不正常的,并希望得到确认,最好是修复。如果现在可以预期,那么我们已经倒退了一大步。无论如何,我该如何修复它以便在 GDB 中正确调试? 顺便说一句,我在多台计算机上都遇到过这种情况。我认为我一直在使用的计算机上有两个不同版本的 Red Hat。我没有在其他 Linux 发行版或 Windows 上测试过。 最可能的解释是您在可执行文件中获得了调试符号,但 gdb 无法读取它们,因为您的发行版具有不理解 dwarf 版本的旧(er)gdb 版本由新(ER)版本的 gcc 生成。解决方案通常是将 gdb 更新到最新版本(可能需要在某些发行版上从源代码构建)。

以上是关于gcc/g++ 不为变量生成调试符号的主要内容,如果未能解决你的问题,请参考以下文章

GCC -g vs -g3 GDB 标志:有啥区别?

《Linux从0到99》四 Linux编译器(gcc/g++)和调试器(gdb)

《Linux从0到99》四 Linux编译器(gcc/g++)和调试器(gdb)

cc,gcc,g++

Linux_gdb调试器

gcc/g++ 编译参数