分离出符号,同时剥离不需要的符号

Separating out symbols and stripping unneeded symbols at the same time

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

现在我知道如何提取调试符号(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-unneeded 删除而不能使用 --strip-debug 删除?或者换句话说:在原始二进制文件上 运行 --strip-unneeded 时,哪些未被 --only-keep-debug 保存在外部符号文件中的符号可能会丢失?有没有办法将这些符号保留在我的外部符号文件中,或者这不是问题?

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

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

我刚刚无意中遇到了同样的问题。 以前我只是将我构建的 ELF 二进制文件与 objcopy 的 --only-keep-debug--strip-debug--add-gnu-debuglink 标志分开。 现在我需要节省更多 space,所以我正在考虑使用 --strip-unneeded 而不是 --strip-debug。 但是和你一样我怕这会影响我的调试体验。

所以,我做了几次测试,得出以下结论:

  1. --strip-unneeded 剥离被 --strip-debug 剥离的内容,甚至更多。 IE。 'debug' 信息被视为 'unneeded' 信息的一部分。
  2. 使用 --only-keep-debug 标志创建的调试二进制文件,不仅存储由 --strip-debug 删除的信息,还存储由 --strip-unneeded.
  3. 删除的信息
  4. 没有注意到在调试 --strip-debug--strip-unneeded 时有任何区别,前提是使用 --only-keep-debug 创建的调试二进制文件。

详情如下:

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

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

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

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

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

考虑文件大小,原始文件明显最大,strip-unneeded 目录中的文件最小,strip-debug 目录中的文件居中。 此外,另外 运行ning --strip-debug 对 strip-unneeded 目录中的文件没有改变文件大小,这意味着 --strip-debug 只剥离了 [=14= 剥离的部分子集].

然后我通过 运行ning 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