如何从共享对象中删除符号?

12
使用GCC,我如何在创建共享对象后从中删除符号?如果我有三个C文件在操作符号foo(),该怎么办:
// a.c
int foo() { return 0xdead; }
int baz() { return 1; }

并且

// b.c
int foo() { return 0xbeef; }
int bar() { return 0; }

并且

// c.c
#include "stdio.h"
extern int foo();
extern int bar();
extern int baz();
int main() { printf("0x%x, 0x%x, 0x%x\n",foo(),bar(),baz()); return 0; }

然后我编译并运行,如下:
% gcc a.c --shared -fPIC -o a.so
% gcc b.c --shared -fPIC -o b.so
% setenv LD_LIBRARY_PATH . # export LD_LIBRARY_PATH=. for bash systems
% gcc c.c a.so b.so -o c
% ./c
0xdead, 0x0, 0x1

我如何做到在创建了a.so之后,使其不再具有符号foo()?我希望使用b.so中定义的foo()代替a.so中的通过从a.so中删除foo()符号。删除a.so中的foo()后,重新运行c应该生成以下输出:

0xbeef, 0x0, 0x1

在这个玩具示例中,我知道当我使用a.sob.so编译c.c时,可以简单地重新排列库名称,但是我如何实际从a.so中删除符号?我想象一旦从a.so中删除了foo(),这个nm输出的grep将不会产生任何结果:
nm -a a.so | grep foo

而现在它返回:

000000000000063c T foo

1
为什么要告诉GCC使用c.c编译a.so和b.so?共享库不应该链接到二进制文件,这就是LD_LIBRARY_PATH的作用。 - Eregrith
1
也许 objcopy 有你需要的一些功能? - Kerrek SB
你有更深入地了解过 strip 吗?我认为你可以通过 -R 来定位文件中的特定符号... - timlukins
2
嗨Eregrith。你是对的,我应该使用“-la -lb”。 - Ross Rogers
2个回答

18

您可以使用objcopy命令的-N(或者--strip-symbol)选项来达到您想要的效果:

$ objcopy -N foo a.so

2
符号可见性似乎是一个更好的解决方案,可以选择哪些函数要进行运行时链接,哪些函数是本地库但仍然被“extern”声明以允许来自包含在库中的其他 .c 文件的使用 - http://gcc.gnu.org/wiki/Visibility

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