-rdynamic仅用于选择符号?

时间:2016-05-10 15:03:01

标签: c linux gcc dynamic-linking dlopen

情景:

可执行文件通过dlopen在运行时加载共享对象。

共享对象引用一些实际编译为主可执行文件的符号(函数)。

如果我在链接可执行文件时将-dynamic添加到gcc,这样可以正常工作。

-rdynamic导出可执行文件的所有非静态符号。我的共享对象只需要少数几个。

问题:有没有办法实现-rdynamic的效果,但是限制了我知道共享对象需要的几个选择符号?

编辑:

至少有两个人误解了这个问题,所以我试着澄清一下:

这个问题是关于从主可执行文件中导出符号。

关于从动态库导出符号,这个问题

这是一个最小的例子:

func.h,公共头文件

#include <stdio.h>
void func(void);

main.c,主要可执行代码:

#include <dlfcn.h>
#include "func.h"

// this function is later called by plugin
void func(void) {
  printf("func\n");
}

int main() {
  void * plugin_lib = dlopen("./plugin.so", RTLD_NOW);
  printf("dlopen -> %p, error: %s\n", plugin_lib, dlerror());

  // find and call function "plugin" in plugin.so
  void (*p)(void); // declares p as pointer to function
  p = dlsym(plugin_lib, "plugin");
  p();

  return 0;
}

plugin.c,运行时加载的插件的代码:

#include "func.h"

void plugin()
{
  printf("plugin\n");
  func();
}

如果我用

编译
$ gcc -o main main.c -ldl
$ gcc -shared -fPIC -o plugin.so plugin.c

然后无法加载plugin.so,因为它引用了无法解析的符号func:

$ ./main
dlopen -> (nil), error: ./plugin.so: undefined symbol: func
Segmentation fault (core dumped)

我可以通过使用-rdynamic编译来说服主可执行文件导出其所有全局符号:

$ gcc -rdynamic -o main main.c -ldl
$ ./main
dlopen -> 0x75e030, error: (null)
plugin
func

但这会使所有符号不必要地填充动态符号表。

(可以使用nm -D main检查此动态符号表。)

问题是,如何只将“func”添加到主可执行文件的动态符号表中,而不是一切。

2 个答案:

答案 0 :(得分:1)

不幸的是,对于可执行文件来说,实现这一目标更加困难。您需要生成要导出的符号列表,然后将-Wl,--dynamic-list=symfile.txt添加到LDFLAGS

Here's example如何在Clang中完成它(以及here用于生成符号文件的脚本。)

答案 1 :(得分:0)

您可以使用GCC的visibility属性来执行此操作。

使用__attribute__ ((visibility ("default")))标志声明导出所需的函数。然后编译整个库,将-fvisibility=hidden参数传递给GCC。

有关此问题的完整说明,请参阅以下GCC documentation page