【问题标题】:Using standard C++ library debug symbols? Ubuntu / Linux / libstdc++6-8-dbg?使用标准 C++ 库调试符号? Ubuntu / Linux / libstdc++6-8-dbg?
【发布时间】:2019-09-07 03:38:39
【问题描述】:

在 Ubuntu Linux 上有一个名为 libstdc++6-8-dbg 的软件包(撰写本文时的最新版本)。

描述为:

GNU 标准 C++ 库 v3(调试文件) 该软件包包含使用编译的 libstdc++ 的共享库 调试符号。

其中包含以下文件:

/usr/lib/x86_64-linux-gnu/debug/libstdc++.a
/usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6.0.25
/usr/lib/x86_64-linux-gnu/debug/libstdc++fs.a

通常用 gcc 编译一个(单翻译单元)C++ 程序可以这样写:

$ g++ myprogram.cc

要添加生成用户代码的调试符号,请传递-g

$ g++ -g myprogram.cc

但这不包括标准库的调试版本。

您需要向g++ 传递哪些额外选项来告诉它使用libstdc++6-8-dbg 提供的标准库的调试版本?

【问题讨论】:

  • 你的目标是什么?您想在调试时访问调试符号,这就足够了吗?或者,也许您只需要它们在运行时可用?我会考虑静态地链接 libstdc++ 的调试版本作为最后的手段。
  • @JohnKugelman:我希望回溯能够在运行时正确符号化 libstdc++ 调用帧。如果您知道 (1) 动态链接调试版本和 (2) 静态链接调试版本的 g++ 命令行,我会感谢您。
  • @JohnKugelman:gdb 不在游戏中。我的意思是在程序运行时,我希望它使用 libstdc++ 的调试版本,以便堆栈跟踪正确地表示其中的任何 libstdc++ 调用。
  • libstdc++6-8-dbg 的数字代表什么?在我的系统上,我被 libstdc++6-10-dbg 所吸引,但有 GCC 版本 9.3.0 和 libstdc++ 版本 3.4。
  • 编译所有警告和调试信息,所以g++ -Wall -Wextra -g myprogram.cc

标签: c++ linux ubuntu gcc libstdc++


【解决方案1】:

安装包后,GDB 会自动读取调试符号。你不需要以任何不同的方式编译你的程序。

如果您希望程序加载调试版本,最好的办法是调整库搜索路径。您可以通过临时设置LD_LIBRARY_PATH 来做到这一点:

$ LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/debug/
$ ldd test
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6 (0x00007efcef670000)
        ...

或永久:

$ export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/debug/
$ ldd test
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6 (0x00007efcef670000)
        ...

或者您可以对其进行系统范围的更改。您可以在 Ubuntu 中通过将配置条目添加到 /etc/ld.so.conf.d/ 并运行 ldconfig 来更新缓存来做到这一点。

$ sudoedit /etc/ld.so.conf.d/debug.conf
$ cat /etc/ld.so.conf.d/debug.conf
/usr/lib/x86_64-linux-gnu/debug
$ sudo ldconfig
$ ldd test
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6 (0x00007f3aced53000)
        ...

配置文件按字母顺序搜索,因此请确保您编写的文件(上面的debug.conf)早于默认文件(我的系统上的x86_64-linux-gnu.conf)。

【讨论】:

  • 好的,但是是否可以链接到调试版本,以便在程序运行时,当程序中生成的堆栈跟踪包含 libstdc++ 调用时,它们会被正确符号化?还是这个包只能与 gdb 一起使用?
【解决方案2】:

OP 希望正确解析回溯中的 C++ 标准库符号。 John's answer 正确地指出,这可以通过链接标准库的调试版本来实现。

不过,Ubuntu 还提供了debug symbol packages,一旦安装,GDB 就可以解析标准库中调试符号已被剥离的符号,即在标准库的release 版本中。我们在下面提供了一个操作示例(我使用的是 Ubuntu 20.04):

假设生成的二进制文件名为 a.out。我们首先找到它链接的 libstdc++ 版本:

$ ldd a.out
        ...
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff8dc6f7000)
        ...

我们搜索提供共享库文件的包(/lib 是指向/usr/lib 的符号链接。这里必须使用完整路径。):

$ dpkg -S /usr/lib/x86_64-linux-gnu/libstdc++.so.6
libstdc++6:amd64: /usr/lib/x86_64-linux-gnu/libstdc++.so.6

按照instructions 添加调试符号包的存储库,然后更新包索引。该链接还描述了如何搜索调试符号包,但我直接使用包名进行搜索:

$ apt list libstdc++6\*
...
libstdc++6-dbgsym/focal-updates 10.2.0-5ubuntu1~20.04 amd64
...

会有很多结果,但一定要注意dbgsym,而不是dbg!安装libstdc++6-dbgsym 后,GDB 应该能够解析符号,即使您的二进制文件没有链接到调试库。


以上文字应回答 OP 的问题。现在我指出约翰的回答存在问题。

安装包后,GDB 会自动读取调试符号。你不需要以任何不同的方式编译你的程序。

此陈述 100% 正确,但包含的数字无关紧要,并不能证明该陈述。这里有三个密切相关的概念:

  • 调试库包:包libstdc++6-8-dbg 提供带有调试符号的libstdc++ 库版本。
  • 调试符号包:包libstdc++6-dbgsym 为libstdc++ 库提供调试符号。也就是说,它不包括任何机器指令,如printf,只有调试符号。 libstdc++6-8-dbg 将代码和调试符号捆绑到一个库中。
  • 发布库包:包libstdc++6-8libstdc++6提供标准库的发布版本,这意味着它们不携带调试符号,只有代码。调试符号包应与发布库一起使用。

GDB 会自动读取调试符号包中的调试符号,而不是调试库中的调试符号。 John 图中的auto-load 简单地说明了 Python 脚本 /usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6.0.25 -gdb.py 会在调试库加载时自动运行,与调试符号的自动加载无关。

【讨论】:

    猜你喜欢
    • 2021-03-01
    • 2019-12-14
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 2019-05-11
    • 2016-12-30
    • 2010-12-28
    • 2021-05-11
    相关资源
    最近更新 更多