“gcc -s”和“strip”命令有什么不同?

108

我想知道这两者之间的区别:

  • gcc -s:从可执行文件中删除所有符号表和重定位信息。

  • strip:从目标文件中丢弃符号。

它们的含义是一样的吗?

你会使用哪一个来:

  • 减小可执行文件的大小?
  • 加速运行?
4个回答

98

gcc是一个编译器/链接器,其-s选项是在链接时完成的。它也不能配置 - 它有一组信息需要删除,没有更多,也没有更少。

strip是可以在已编译的目标文件上运行的工具。它还有各种命令行选项,您可以使用这些选项来配置要删除哪些信息。例如,-g只会删除gcc -g添加的调试信息。

请注意,strip不是一个bash命令,尽管您可能正在从bash shell中运行它。它是与bash完全分离的命令,是GNU二进制实用程序套件的一部分。


1
谢谢!在strip中,有哪些选项相当于gcc -s? - Tim
3
你用哪个工具来减小可执行文件的大小并加速运行速度? - Tim
1
我认为strip的默认行为类似于gcc -s,但我不是专家。如果你真的需要知道,请等待另一个答案。个人而言,我会避免在这个领域里搞清楚任何你不完全理解的东西。我相当确定你应该期望可执行文件大小减小,但执行速度不会有显著变化。 - Cascabel

62

接受的答案非常好,但是为了补充您进一步的问题(并且也作为任何人参考的参考),以下是需要翻译的内容:

在削减大小和加快运行速度方面,gcc -s 的相当于strip的选项是什么?

它们都执行相同的操作,彻底删除符号表。然而,正如@JimLewis所指出的,strip具有更细致的控制能力。例如,在可重定位目标文件中,strip --strip-unneeded 不会删除其全局符号。但是,strip 或者 strip --strip-all 将删除完整的符号表。

你使用哪一个来缩小可执行文件的大小并加快其运行速度?

符号表是二进制文件中的不可分配部分。这意味着它永远不会被加载到RAM内存中。它存储的信息可以用于调试目的,例如,在崩溃发生时打印出堆栈跟踪。如果您有严格的存储容量限制的情况下,移除符号表可能有意义的场景,gcc -Os -s 或者 make CXXFLAGS="-Os -s" ... 是有用的,因为它将产生一个更小、更慢的二进制文件,并通过削减大小来进一步缩小。我认为移除符号表不会带来运行速度的提升。

最后,我推荐这个关于剥离共享对象的链接:http://www.technovelty.org/linux/stripping-shared-libraries.html


4
+1 表示“二进制文件中不可分配的部分”,而“删除符号表不会导致速度提升”。 - Makesh
1
它从不被加载到RAM内存中。那么为什么man strip会说:“剥离的二进制文件将占用更少的RAM空间”呢? - YvesgereY
1
@YvesgereY:我认为这是一个有些乐观的说法。如果内核的文件预读算法恰好拉取了该页面而不是有用的页面,则它在磁盘上占用的空间更少,在RAM中的页面缓存中也是如此。或者如果二进制文件中的任何部分确实需要与符号表一起加载到同一个4k页面中,那么可能会将大部分无用数据的页面拉入内存。(例如,用于动态链接的符号表的一部分。)我实际上不确定用于动态链接的符号是否被分组在一起,还是与“无用”的调试符号混合。 - Peter Cordes
关于剥离共享对象的相关文章非常好。 - drlolly

26

"gcc -s" 命令可以删除重定位信息和符号表,而 "strip" 命令只能删除符号表。请注意,删除重定位信息会对地址空间布局随机化产生一些影响。请参见此链接


3
第一个回答需要明确提到究竟移除了什么!如果能给出被移除的章节的具体清单,那就更好了。 - Victor Sergienko

7

他们的作用类似,但是strip功能可以更细粒度地控制需要从文件中删除的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接