dlopen / dlsym с минимальным количеством ссылок - PullRequest
1 голос
/ 10 апреля 2010

У меня есть приложение, которое может использовать плагины, которые загружаются во время выполнения с использованием 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 ]

1 голос
/ 10 апреля 2010

По man dlopen (акцент мой)

RTLD_LAZY

Выполнить ленивую привязку.
Разрешать только символы как код, который ссылки на них выполнены. Если символ никогда не ссылается, то это никогда не разрешается. (Ленивый переплет выполняется только для функции Рекомендации; ссылки на переменные всегда немедленно связаны, когда библиотека загружена.)

Так что вам нужно добавить в свой инструмент все глобальные переменные, которые ваш плагин может использовать.

1 голос
/ 13 апреля 2010

Если вы используете двоичные файлы elf, вы можете посмотреть, есть ли на вашей платформе libelf. Попробуйте man elf для получения дополнительной информации. Это может дать вам то, что вам нужно, без необходимости на самом деле ссылки. Я никогда этим не пользовался, поэтому не знаю.

0 голосов
/ 10 апреля 2010

Как насчет грязного хака с 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.      

...