2011-05-31 67 views
7

我有一个共享库(bar.so)链接到一个更大的程序(foo)的插件。 foo和bar.so都依赖于相同的第三方库(baz),但他们需要将baz的实现完全分开。所以当我链接foo(使用提供的对象文件和档案)时,我需要它忽略bar.so中任何对baz的使用,反之亦然。如何限制访问共享对象中的符号?

现在如果我链接foo且--trace-symbol=baz_fun其中baz_fun是有问题的符号,我得到了下面的一个输出:

bar.so: definition of baz_fun 
foo/src.a(baz.o): reference to baz_fun 

我相信这是告诉我,FOO被引用从bar.so baz_fun(和foo的执行证实了这一点)。

的解决方案,我曾尝试:

  • 使用objcopy以“本地化”感兴趣的符号:objcopy --localize-symbols=local.syms bar.so其中local.syms包含了所有感兴趣的符号。我想我可能只是在这里感到困惑,也许“本地”并不意味着我认为的意思。无论如何,我从上面的链接获得相同的输出。我应该注意到,如果我在bar.so上运行nm工具,那么在使用objcopy之前,所有符号都有T标志(大写字母表示全局),并且在objcopy之后,它们有一个t表示它们现在是本地的。所以看来我正确使用objcopy
  • 编译与-fvisibility=hidden然而,由于一些其他限制,我需要使用GCC 3.3,似乎不支持该功能。我可能可以升级到GCC的较新版本,但希望确认使用此标志进行编译将有助于我在前往该道路之前。

其他注意事项:

  • 我没有访问foo或巴兹
  • 的源代码,我宁愿让我所有的插件在一个共享对象( bar.so)。 baz实际上是一个许可证库,所以我不希望它分开

回答

3

使用dlopen加载您的插件与RTLD_DEEPBIND标志。

(编辑)

请注意,RTLD_DEEPBIND是Linux特有的和需要的glibc 2.3.4或更高版本。

+0

也许我误解了,但是如果我没有访问加载插件bar.so的foo的源代码,我该怎么做? – brady 2011-06-01 13:08:58

+0

好的,如果你只控制栏而不是foo,你可以在两个库bar1和bar2中拆分栏。 bar1提供插件接口并将所有呼叫转发到bar2,而bar2实现所有内容。 bar1应该调用'dlopen(“libbar2.so”,RTLD_NOW | RTLD_DEEPBIND)''和'dlsym'所有需要的函数。或者你可以保留一个栏,并从那里保存“dlopen(”libbaz.so“,RTLD_NOW | RTLD_DEEPBIND)”和“dlsym”所有你需要的功能。使用任何方法都需要更少的电话到'dlsym'。 – 2011-06-01 13:52:30