分离符号并同时剥离不需要的符号

时间:2017-09-13 12:37:55

标签: debug-symbols objcopy

我有兴趣创建一个外部符号文件,我使用objcopy --add-gnu-debuglink=...从我的ELF文件中引用该文件。

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

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

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

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

任何人都可以解释可能会通过--strip-unneeded删除哪些符号可能无法通过--strip-debug删除?或者换一种说法:在原始二进制文件上运行--only-keep-debug时,--strip-unneeded未在外部符号文件中保留哪些符号可能会丢失?有没有办法在我的外部符号文件中保留这些符号,或者这不是问题吗?

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

PS:我知道How to generate gcc debug symbol outside the build target?但是这个问题及其答案并没有触及我所询问的细节。

1 个答案:

答案 0 :(得分:2)

我偶然发现了同样的问题。 以前,我只是用objcopy的--only-keep-debug--strip-debug--add-gnu-debuglink标志来分隔构建的ELF二进制文件。 现在,我需要节省更多空间,因此我正在考虑使用--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

考虑到文件大小,原始文件显然是最大的文件,带区不需要的dir文件中的文件最小,并且带调试的dir文件中的文件位于中间。 另外,对不需要删除的目录中的文件另外运行--strip-debug并不会更改文件大小,这意味着--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_line.debug_str,还包含.symtab.strtab。这些部分的大小几乎与原始大小相同。

然后,我尝试逐步调试所有三个变体,但没有注意到它们之间的任何区别。另外,我已经使用所有崩溃和核心转储进行了崩溃,然后尝试针对核心转储进行调试-两者也没有区别。

使用的版本: gcc(Ubuntu 5.4.0-6ubuntu1〜16.04.10)5.4.0 20160609 GNU objcopy(适用于Ubuntu的GNU Binutils)2.26.1 GNU Strip(适用于Ubuntu的GNU Binutils)2.26.1