【问题标题】:-rdynamic for select symbols only?-rdynamic 仅用于选择符号?
【发布时间】:2017-11-30 00:29:08
【问题描述】:

场景:

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

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

如果我在链接可执行文件时将 -rdynamic 添加到 gcc,这会很好。

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

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

编辑:

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

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

这个问题不是关于从动态库中导出符号的问题。

这是一个最小的例子:

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”添加到主可执行文件的动态符号表中,而不是全部。

【问题讨论】:

标签: c linux gcc dynamic-linking dlopen


【解决方案1】:

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

Here's example 是如何在 Clang 中完成的(here 是他们用来生成符号文件的脚本)。

【讨论】:

【解决方案2】:

您可以使用 GCC 的可见性属性来做到这一点。

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

对此的完整解释,请参考以下GCC documentation page

【讨论】:

  • 谢谢,但不。我的问题是关于从主可执行文件中导出符号,而不是从库中。
猜你喜欢
  • 1970-01-01
  • 2012-01-27
  • 2013-05-31
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
  • 2019-05-24
  • 2023-03-14
相关资源
最近更新 更多