11

我有兴趣创建一个外部符号文件,我使用objcopy --add-gnu-debuglink=....

现在我知道如何提取调试符号 ( objcopy --only-keep-debug) 以及如何去除调试符号 ( objcopy --strip-debug)。

但是,我想删除所有不需要的符号。我知道这可以通过objcopy --strip-unneeded. 调试符号和不需要的符号是两个不同的类别和两个不同的命令行开关这一事实表明可能存在不重叠的符号。

由于不需要的符号似乎不仅仅包含调试符号,因此我害怕在执行此操作时会丢失一些符号信息(在 GNU make 中):

stripped/%: %
    objcopy --only-keep-debug $@ $@.dbg
    objcopy --strip-unneeded $@
    objcopy --add-gnu-debuglink=$@.dbg $@

谁能解释一下哪些符号可以通过--strip-unneededthat may not be removed with 来删除--strip-debug?或者换一种说法:在原始二进制文件上运行时,哪些未保存在外部符号文件中的符号--only-keep-debug可能会丢失?--strip-unneeded有没有办法将这些符号保留在我的外部符号文件中,或者这不是问题?

目标是能够使用外部调试符号来调试问题,而不至于错过一些符号信息而发现为时已晚。所以我不想丢失符号信息,我只想从程序二进制文件中完全删除它。

PS:我知道如何在构建目标之外生成 gcc 调试符号?但是这个问题及其答案并没有触及我所询问的细节。

4

1 回答 1

11

我刚刚偶然发现了同样的问题。以前我只是将我构建的 ELF 二进制文件与 objcopy 的--only-keep-debug, --strip-debug,--add-gnu-debuglink标志分开。现在我需要节省更多空间,所以我正在考虑使用--strip-unneeded而不是--strip-debug. 但是和你一样,我担心这可能会影响我的调试体验。

因此,我进行了多次测试并得出以下结论:

  1. --strip-unneeded剥去被剥去的东西--strip-debug,甚至更多。即“调试”信息被视为“不需要”信息的一部分。
  2. 使用该标志创建的调试二进制文件--only-keep-debug不仅存储由 .--strip-debug剥离的信息,还存储由--strip-unneeded.
  3. 如果使用--strip-debug. _ --strip-unneeded_ --only-keep-debug_

详情如下:

我创建了一个非常简单的 C++ 项目,其中包含一个可执行文件和一个共享库。该库包含一个全局导出的函数,由应用程序调用。该库还包含几个局部函数(即静态或在匿名命名空间中),由全局导出函数调用。本地函数中的代码只是通过抛出未处理的异常而导致崩溃。

首先,我用-g -O0标志编译了两个二进制文件。其次,我在单独的二进制文件中从它们中提取了调试信息,并将这些调试文件链接到原始二进制文件。即,对于两个文件:

objcopy --only-keep-debug $FILE $FILE.debug
objcopy --add-gnu-debuglink=$FILE.debug $FILE

在此之后,我有未剥离的二进制文件也有单独的对应链接调试二进制文件。

然后我将这些文件复制到另外两个目录中。在第一个中,我--strip-debug对原始二进制文件进行了处理,在另一个中,我完成了--strip-unneeded.

考虑文件大小,原始文件明显最大,strip-unneeded 目录中的文件最小,而 strip-debug 目录中的文件位于中间。此外,另外--strip-debug对 strip-unneeded 目录中的文件运行并没有改变文件大小,这意味着--strip-debug只去除被--strip-unneeded.

然后,我通过运行readelf -S所有三个变体来比较所有三个变体的部分列表。查看它们,可以看出--strip-debug剥离了以下部分:.debug_arranges.debug_info.debug_abbrev.debug_line.debug_str,并且还稍微减少了.symtab.strtab部分。 --strip-unneeded另外还完全删除.symtab.strtab部分。

然后我运行readelf -S了带有--only-keep-debug标志的调试二进制文件。那里的部分已删除所有部分--strip-unneeded。因此,它不仅包含.debug_arranges, .debug_info, .debug_abbrev, .debug_lineand .debug_str, 而且还包含.symtaband .strtab。并且这些部分的尺寸几乎与它们的原始尺寸相同。

然后我尝试逐步调试所有三个变体,并没有注意到它们之间有任何区别。此外,我已经产生了所有这些崩溃和核心转储,然后尝试针对核心转储进行调试 - 也没有区别。

使用的版本: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609 GNU objcopy (GNU Binutils for Ubuntu) 2.26.1 GNU strip (GNU Binutils for Ubuntu) 2.26.1

于 2018-09-28T12:14:34.017 回答