如何从共享库中删除*所有*未使用的符号?

6

我有一段代码需要编译为共享库,并删除其中所有未使用的代码,但是我找不到一个合适的解决方案。以下是一个简单的示例:

// test.cpp, compiled with GCC -fPIC -shared -fvisibility=hidden
#include <stdio.h>
class Foo {
    void bar();
};
void Foo::bar() { printf("hello"); } // unused and should be removed
// I'm using printf("hello") so I can detect the symbols with `strings`

__attribute__((visibility("default"))) void test() {} // this function is "used"

"-fvisibility=hidden"的作用是默认情况下所有函数都被隐藏,我手动使用"__attribute__((visibility("default")))"标记公共函数。然而,除非将隐藏函数标记为"static"(这显然无法应用于C++方法),否则它们不会被删除。
无论我做什么,GCC始终会保留"void Foo::bar()"和"hello"。有没有一种方法可以在不篡改编译器的情况下删除这些符号?(是的,我现在正在考虑这个问题!)
谢谢!

请解释一下为什么你想要这样做。 - bmargulies
声明所有函数为静态的? - Mats Petersson
@MatsPetersson:这对于C++成员函数是行不通的。 - Dietrich Epp
1
@bmargulies:有很多合理的解释。它可能是一个受限制的环境,或者它可能链接到一个第三方静态库,其中只使用了一小部分等等。删除未使用的符号也会导致dylib依赖项消失,因此有时您可以从中获得很多好处。 - Dietrich Epp
1
你能解释一下你想要实现什么吗?这似乎是一个 XY 问题:http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem - R.. GitHub STOP HELPING ICE
显示剩余4条评论
1个回答

7
使用标志-ffunction-sections进行编译。然后使用-Wl,--gc-sections进行链接。我认为这也可以通过LTO实现,但我不确定细节。
请注意,dylib中的所有公共符号都被视为活动的。只有隐藏的符号会被这种方式剥离。

这也可以,但我还发现了GCC的-fwhole-program标志,它基本上将每个函数标记为静态,从而允许进行积极的代码删除(http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html)。 - user2662514
@user2662514:只有当你的库的源代码包含在单个文件中时,这才有效。 - Dietrich Epp
2
@user2662514:这个解决方案的原理是链接器不是在符号级别检查,而是在节级别检查(一个节可能包含多个符号)。通过向gcc传递“-ffunction-sections”,您指示编译器将每个函数发射到自己的节中;您应该期望它会显着减慢链接阶段,但另一方面,链接器现在可以从库中剥离更多的代码。 - Matthieu M.

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