【问题标题】:Separating out symbols and stripping unneeded symbols at the same time分离符号并同时剥离不需要的符号
【发布时间】:2017-09-13 12:37:55
【问题描述】:

我有兴趣创建一个外部符号文件,我使用 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? 但这个问题及其答案并没有触及我所询问的细节。

【问题讨论】:

  • 我发现this article 有一些有用的信息。甚至可以回答这个问题。
  • @mshildt:确实有用。谢谢。不幸的是,它没有回答问题,即如果我仅将调试符号提取到外部文件中,然后在原始文件上使用 --strip-unneeded,哪些符号可能会丢失。

标签: debug-symbols objcopy


【解决方案1】:

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

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

  1. --strip-unneeded 剥离 --strip-debug 剥离的内容,甚至更多。 IE。 “调试”信息被视为“不需要”信息的一部分。
  2. 调试使用--only-keep-debug 标志创建的二进制文件,不仅存储--strip-debug 剥离的信息,还存储--strip-unneeded 剥离的信息。
  3. 如果使用--only-keep-debug 创建的调试二进制文件,我没有注意到--strip-debug--strip-unneeded 的调试有任何区别。

详情如下:

我创建了一个非常简单的 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-unneeded 目录中的文件另外运行 --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 条(Ubuntu 的 GNU Binutils)2.26.1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2011-08-10
    • 2012-10-22
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    相关资源
    最近更新 更多