dlopen / dlsym尽可能少的链接

时间:2010-04-10 17:35:23

标签: c dynamic linker dlopen

我有一个应用程序可以使用在运行时使用dlopen加载的插件。每个插件定义用于检索使用公共结构定义的插件信息的功能。这样的事情:

struct plugin {
    char *name;
    char *app_version;
    int app_verion_id;
    char *plugin_version;
    int plugin_version_id;
    /* ... */
 };

 struct plugin p = { "sample plugin",APP_VERION,APP_VERSION_ID,"1.2.3",10203 };

 struct plugin *get_plugin() {
     return &p;
 }

这很好用,可以加载插件。现在我想构建一个小工具来读取这些属性而不链接整个应用程序。为此,我有一些像这样的代码:

void *handle;
struct plugin *plugin;
struct plugin *(get_plugin*)();

handle = dlopen(filename, RTLD_LAZY);
if (!handle) { /*...return; ...*/ }

get_plugin = dlym(handle, "get_plugin");
if (!get_plugin) { /*...return; ...*/ }

plugin = get_plugin();
printf("Plugin: %s\n", plugin->name);

这适用于简单的插件。问题是许多插件引用了应用程序中的其他符号,即使设置了RTLD_LAZY也会解析这些符号。 (就像应用程序中用于初始化插件全局事物的全局变量一样)所以dlopen()调用失败并出现fatal: relocation error: file sample_plugin.so: symbol application_some_symbol: referenced symbol not found之类的错误。由于我只想访问单个简单结构,我想知道如何阻止链接器完成他的大量工作。

3 个答案:

答案 0 :(得分:1)

根据man dlopen(强调是我的)

  

RTLD_LAZY

     

执行延迟绑定   只解析符号作为代码   引用它们是执行的。如果   符号永远不会被引用,那么它   永远不会解决。 (懒惰的绑定是   仅针对功能执行   引用;对变量的引用   总是立即束缚   库已加载。)

因此,您需要在工具中添加插件可能使用的所有全局变量。

答案 1 :(得分:1)

如果您使用的是精灵二进制文件,则可能需要查看您的平台是否具有可用的libelf。 请尝试man elf了解详情。这可以为您提供所需而无需实际链接。我从来没用过它,所以我不知道。

答案 2 :(得分:0)

objdump的肮脏黑客怎么样:

~$ objdump -s -j .rodata plugin.so  

plugin.so:     file format elf32-i386

Contents of section .rodata:
 20000000 73616d70 6c652070 6c756769 6e00332e  sample plugin.3.
 20000010 322e3100 312e322e 3300               2.1.1.2.3.