У меня есть сторонняя библиотека (скажем, libfoobar.so
), которая зависит от другой сторонней библиотеки под названием libutils.so
. У меня есть только старая версия libutils.so
, в его старой версии отсутствует символ (экспортированная функция), который существует только в новой версии.
Я могу закодировать функцию в новой общей библиотеке (скажем, libwrapper.so
):
extern "C" int missing_function() {
return 123;
}
И сейчас?? как можно "сказать" libfoobar.so
использовать эту функцию, уже пробовал:
libwrapper.so
перед libfoobar.so
.patchelf --add-needed libwrapper.so libfoobar.so
. Но я понимаю dlopen failed: empty/missing DT_HASH in "libfoobar.so" (built with --hash-style=gnu?)
Я не могу использовать "новую версию" из соображений совместимости. Есть какое-нибудь решение?
Хорошо, я решил проблему странным образом, создав «прокси»-библиотеку, которая обертывает используемые функции.
Шаг, следующий за предыдущим примером:
libfoobar.so
в шестнадцатеричном редакторе и исправить (изменить) ссылку на новую общую библиотеку, заменив строку libutils.so
на libutilx.so
(соблюдайте количество символов)LIBSUTILS
на LIBUTILX
libutilx.so
. Пример кода C нижеlibfoobar.so
и ГОТОВО.#include <dlfcn.h>
void *lib = dlopen("libutils.so", RTLD_LAZY);// original lib
// delegates
void *(*ORIGmalloc)(size_t size);
int (*ORIGpthread_setspecific)(pthread_key_t key, const void *value);
// functions
extern "C" void *malloc(size_t size) {
return (*ORIGmalloc)(size_t);
}
extern "C" int pthread_setspecific(pthread_key_t key, const void *value) {
return (*ORIGpthread_setspecific)(pthread_key_t, value);
}
// implements missing functions in libutils.so required by libfoobar.so
extern "C" const char *get_greeting_string() {
return "Hello from libutilx.so !!";
}
extern "C" int some_number() {
return 12345;
}
// assigns (just an example, you must check for errors)
// with the attribute "constructor" this function is called after the lib is opened
void __attribute__((constructor)) assign_delegates() {
*(void **) (&ORIGmalloc) = dlsym(lib, "malloc");
*(void **) (&ORIGpthread_setspecific) = dlsym(lib, "pthread_setspecific");
}
Чтобы узнать, какие функции импортируются, используйте утилиту командной строки objdump. Пример objdump -T libfoobar.so
вывод будет:
00000000 DF *UND* 00000000 LIBUTILS pthread_setspecific
00000000 DF *UND* 00000000 LIBUTILS malloc
00000000 DO *UND* 00000000 LIBUTILS __sF
ваше здоровье