`dlopen` DSO изнутри того же DSO - PullRequest
       30

`dlopen` DSO изнутри того же DSO

0 голосов
/ 05 апреля 2019

У меня есть DSO (библиотека mylibrary.so.0) с функцией func1, помеченной как extern "C", и я уверен, что она экспортируется с

nm -D mylibrary.so.0 | grep func1
000000000009f9bb T func1 <- symbol is visible and exported

Этот DSO загружается в цепочкузависимостей, которые я не могу контролировать, например,

executable1 -dlopen-> 3rdpartydispatcher.so -dlopen-> my_library.so.0

Теперь в моей библиотеке есть метод, который вызывается (я вижу, что он вызывается путем входа в него через gdb) и получаетстрока C с именем функции, которую она должна вызывать, например,

void call_function_from_name(const char *function_name) {

    void *mylibrary_so_0 = dlopen(NULL, RTLD_NOW); // (*)
    void *func1 = dlsym(mylibrary_so_0, function_name);
    if (!func1) {
        log_error(dlerror());
    }
    ...
}

Проблема заключается в том, что даже если call_function_from_name вызывается с аргументом func1, то есть совершенно допустимым и экспортируемым символом, dlsymОшибка и ошибка executable1 has no func1 symbol.

Я пришел из среды Windows, и я предположил, что dlopen(NULL, ..) возвращает мне дескриптор основного исполняемого файла , но , что любой последующий dlopenбиблиотека из этого исполняемого файла также отображается в его виртуальном адресном пространстве, и поэтому я могу использовать этот дескриптор для поиска символов, которые экспортировали эти библиотеки.

Является ли мое предположение неверным?Если это так, как я могу сослаться на func1 в вызове функции same-dso?

Ответы [ 2 ]

0 голосов
/ 08 апреля 2019
`void *mylibrary_so_0 = dlopen(NULL, RTLD_NOW); // (*)`

Почему-то вы считаете, что это должно dlopen my_library.so.0, но не - он открывает основной исполняемый файл.

Сообщение об ошибке ясно говорит вам, что: executable1 has no func1.

Возможное исправление - это использование dlopen("my_library.so.0", RTLD_NOW), но гораздо лучше исправить это, чтобы предоставить статическую карту функций, которую вы хотитечтобы иметь возможность вызывать этот способ и использовать , что :

struct mapping { const char *f_name; void (*f_ptr)(); } = {
  { "func1", &func1 },
  { "func2", &func2 },
  { NULL, NULL },
};

Теперь просто найдите ваш mapping и вызовите целевую функцию;нет dlsym требуется.

0 голосов
/ 05 апреля 2019

Ваша библиотека, вероятно, была загружена RTLD_LOCAL, которая явно не помещает ее в глобальное пространство символов.Он может вызвать dlopen для себя с RTLD_GLOBAL, чтобы «исправить» это, если необходимо, или, если вы знаете, что нужный символ находится в вашей библиотеке, он может просто получить новый дескриптор RTLD_LOCAL и вызвать dlsym наэто, а не глобальное пространство имен.

...