在开发过程中将调试符号附加到系统库的最佳实践?

在开发过程中将调试符号附加到系统库的最佳实践?

我正处于项目的某个阶段,安装系统包的调试版本会非常方便。至少在 Ubuntu 上,将调试符号添加到库中是小菜一碟。实际上每个包都有一个-dbg变体,它提供了有用的回溯所需的所有符号。

然而,我目前使用的是 Arch linux,其中普遍共识是编辑用户makepkg.conf文件,将任何调试标志添加到(C|CXX|CPP|LD)FLAGS.然后自己重​​新构建包,并用调试版本替换当前的优化版本。好吧,我认为这对于“基于源的发行版”来说是足够公平的,但它很快就会变得乏味。

那么,将调试符号附加到系统包的最佳实践是什么?其他包装商是如何做到的?

我想我已经看到strip可以提取调试符号并将它们保存在外部文件中。是否有可能gdb在回溯期间拾取这些符号文件,而系统应用程序甚至懒得寻找它们?从包装商的角度来看,这是如何运作的?

这只是一个想法,但创造一个chroot发展环境是一个好主意吗? (我有一个问题 atm,其中一个包的调试版本和发布版本之间存在 ABI 不兼容,这有点痛苦。链接到其共享库的所有内容也会抱怨缺少符号,因此恢复为优化版本..)

答案1

如果您分发一个来源包中,(autotools)规范是默认编译调试符号。

我认为曾经主流的 Linux 发行版也将它们保留在二进制文件中;我对此可能是错的。有一种误解认为删除调试符号可以“优化”软件。事实并非如此。包含调试符号造成的唯一区别是文件在磁盘上占用的空间。它不会影响内存使用,因为它们在正常使用期间不会加载到内存中(因此,它也不会影响其他任何内容)。尝试分析已剥离和未剥离的二进制文件。他们是一样的。

将它们从发行版包中拆分出来的目的只是为了减小每个包的大小,以便整个安装的大小为 2.5 GB,而不是 3.8 GB 或其他大小。如果您的包被选择包含在官方存储库中,则发行版将从源代码中打包它。他们不会使用您预先制作的包,因此您现在执行此工作(创建单独的调试包)不会在这方面产生影响。

如果您独立地为各种发行版分发库二进制包,那么没有人会关心调试符号是否被编译进去,并且大多数使用该库进行编程的人都会需要它们。对于少数因某种奇怪原因而烦恼的人来说,无论如何,它们很容易被剥夺。

所以,如果你想听听我作为程序员和 Linux 用户的意见,请把它们留下来,至少现在是这样。明显关注“过早优化”——尤其是并非真正优化的过早优化——看起来并不好。换句话说,你的问题的字面答案是:“最佳实践在开发过程中将调试符号附加到系统库的方法是将它们编译成”。

也就是说,我确实注意到了本页 WRT .deb 包当我试图证实我的信念时,从前他们总是被包括在内。由于您在标签中包含了 dpkg,因此它可能对您有用。

答案2

添加OPTIONS+=(debug !strip)将此(来自/etc/makepkg.conf)添加到您的构建选项中:DEBUG_CFLAGS="-g -fvar-tracking-assignments"

这些都不会禁用任何优化(https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html)。您可以获得带有调试符号的优化构建,不是当许多人谈论“调试构建”时,他们的意思是什么。为此,您还可以启用-O0-Og(“优化调试”。)

当您使用 gdb 进行调试时,通常print some_local会给出(optimized out),因为调试格式无法跟踪寄存器中存在的变量(不会溢出到内存)。当然,即使是完美的调试格式也无法真正修复变量确实被优化掉的情况,并且没有寄存器或内存保存与 C 源代码匹配的值。您仍然可以(相当)可靠地获取回溯,并将函数参数传递给未内联的函数。


https://wiki.archlinux.org/index.php/Debug__-_Getting_Traces目前表示您现在可以使用(debug strip)获取一个单独的somepkg-debug包来将符号信息放入/usr/lib/debug. (就像 Debian/Ubuntu 的分发方式一样somepkg-dbg。)我不知道 2013 年你问这个问题时是否就是这种情况。

当然,您不能将该调试包与现有的二进制包一起使用,因为任何微小的差异都可能导致错误的调试信息。

不幸的是,没有用于为预构建的二进制包分发调试包的存储库/包系统。因此,您仍然需要在本地编译您想要调试符号的任何包。

从好的方面来说,这是一个-march=native专门针对您的系统优化二进制文件的好机会。例如,启用 CPU 支持的所有功能,例如用于更高效的可变计数移位指令的 BMI2、硬件popcnt以及 AVX / AVX2 / FMA / AVX512 向量指令。 -march=native还设置-mtune=native,这很好

将调试信息保留在与库相同的文件中的性能开销应该可以忽略不计。整个内容/usr/lib/libc.so.6不会加载到 RAM 中,只有需要的页面才会被映射。调试信息在二进制文件中分组在一起,因此这些页面可能在磁盘上保持冷状态。

相关内容