【发布时间】: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”添加到主可执行文件的动态符号表中,而不是全部。
【问题讨论】:
-
@ninjalj 不错的发现!这个问题本身不是我的问题。但它有一个答案stackoverflow.com/posts/6298434/revisions 也回答了我的问题。
-
@LudwigSchulze:我已经展示了一个明确的例子来说明如何做到这一点in this answer。最初的问题与您在这里的情况几乎完全相同。
标签: c linux gcc dynamic-linking dlopen