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
)。输出包括aFunction
和main
,但不包括argc
和intVariable
。
我已经阅读了很多问题/答案/帖子/文章/等。试图弄清楚为什么 gcc/g++ 没有为我的变量生成调试符号,但我无法解决这个问题。大多数来源只提到-g
、-O0
、-Og
,并避免-s
和编译优化。
我需要在 gdb 中进行调试的符号。如果我做gdb a.out
然后break main
,让它运行并中断,然后bt
确认我在main
和print argc
或print 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++ 不为变量生成调试符号的主要内容,如果未能解决你的问题,请参考以下文章
《Linux从0到99》四 Linux编译器(gcc/g++)和调试器(gdb)