【问题标题】:How can I remove a symbol from a shared object?如何从共享对象中删除符号?
【发布时间】:2012-03-28 14:23:16
【问题描述】:

使用 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 在我创建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

【问题讨论】:

  • 你为什么告诉你的 GCC 用你的 c.c 编译 a.so 和 b.so ?共享库不应该链接到您的二进制文件,这就是 LD_LIBRARY_PATH 的用途。
  • 也许objcopy 有一些你需要的功能?
  • 您是否更全面地查看了strip?我相信您可以使用 -R... 定位文件中的特定符号
  • 嗨,埃瑞格里斯。你说得对,我应该使用-la -lb

标签: c linux gcc shared-libraries


【解决方案1】:

您应该可以使用objcopy-N (--strip-symbol) 选项来实现您想要的:

$ objcopy -N foo a.so

【讨论】:

    【解决方案2】:

    符号可见性似乎是一种优越的解决方案,可以选择哪些函数用于运行时链接,哪些函数是库本地的,但仍声明“外部”允许从构成库的其他 .c 文件使用 - http://gcc.gnu.org/wiki/Visibility

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-25
      • 2011-04-25
      • 2011-09-05
      • 2010-11-17
      相关资源
      最近更新 更多