我在尝试使用gdb为使用libtool构建的软件包调试测试程序时遇到了一个奇怪的问题。如果我运行libtool --mode=execute gdb .libs/libfoo.so
并要求它列出某个函数list Bar::Baz
的源代码,我会按预期获得源代码。如果我运行libtool --mode=execute gdb binary
,我可以进入Bar::Baz()
,并在堆栈跟踪中查看其参数,但我没有得到源文件或行号,如下所示:
#7 0x018348e5 in Bar::Baz(Qux*, Quux*) () from /path/to/libfoo.so
^^^^^^^^^^^ <--- debug symbols are present!
同样,如果我在调试可执行文件时尝试list Bar::Baz
,我会得到
No line number known for 'Bar::Baz'.
我已确认二进制文件与-g
链接,我可以列出其main
函数,因此我知道存在一些调试信息。
当我说info sources
时,我会得到一个完整的文件列表,其中包含正确的绝对路径。当我说info shared
时,我会在目标文件中找到正确的路径,Yes
列中有Syms
。
任何进一步的想法可能出错,以及如何解决它?
编辑1:不小心,我在有问题的库上运行了objdump -g
,得到了以下输出:
/path/to/foo.so.0.0.0: file format elf32-i386
objdump: /path/to/foo.so.0.0.0: no recognized debugging information
这是令人惊讶的,因为objdump -h
(我试图运行的)列出了一堆.debug_*
部分。 objdump
手册也提示readelf -w
,这似乎打印了大量信息。不过,我需要仔细研究它实际提供的内容。
编辑2:所以,readelf -w
已经产生了一些启示。无论出于何种原因,共享对象文件似乎不包含来自的绝大多数 任何链接到其中的对象的调试信息。基于Makefile,实际上将对象收集到共享库中的命令可能不会传递-g
,因此信息传播不正确。有趣的是,这对我们所有其他配置都有效(包含完整的调试信息),包括x86_64上的相同编译器版本(与现在的x86相比)。
编辑3:实际上在LDFLAGS上添加了-g时使用修改后的Makefile进行了完全重建,但没有任何区别。现在我很好,真的很困惑。
答案 0 :(得分:5)
这是一个老问题的答案,但你的问题与我的问题相符,但没有一个解决方案有效。这对我有用。
将CFLAGS -g更改为“-g -gstabs”。
objdump没有认识到矮人风格的调试信息。 -gstabs将此格式更改为与objdump -g和objdump -S以及我的调试器一起使用的格式。
希望它有所帮助。
注意:对我来说,我正在构建一个Linux内核。这个更改是在linux内核的Makefile中生成的。
答案 1 :(得分:2)
您的第一个困惑点:Bar::Baz(Qux*, Quux*)
不暗示调试符号存在(实际上暗示它们不存在)。
调试器只是对函数名称进行解码。如果调试符号实际存在,您会看到Bar::Baz(Qux* qux = 0x12..., Quux* quux = 0x234...)
至于真正的问题,我怀疑该符号是在某些其他库中定义的,
libfoo.so
之前的二进制文件的链接行,(运行时加载器会将对Bar::Baz()
的引用绑定到它看到的第一个定义。)
如果您在第7帧中打印ip
,然后执行info symbol <value-just-printed>
,我怀疑您会有“啊哈!”时刻。
编辑:您的更新使您的问题自我不一致。 AFAICT,
gdb
可以看到调试符号
libtool --mode=execute gdb .libs/libfoo.so
libtool --mode=execute gdb binary
.libs/libfoo.o
readelf -w
在.libs/libfoo.o
上述陈述中至少有一项可能是错误的。
如果它们都是真的,那么你可能有一个奇怪的GDB
和 readelf
错误(一个错误可能存在,两者同时存在错误)。
另请注意,将-g
添加到LDFLAGS
通常是错误的要做的事情。您的意思是将其添加到CXXFLAGS
吗?
答案 2 :(得分:0)
有些东西让我想知道当你遇到show language
时的输出是什么
问题。如果不是c++
,可能需要set language c++
吗?