在共享库上实现缺失符号
Implement missing symbol on a shared library
我有一个第三方库(比如 libfoobar.so
)依赖于另一个名为 libutils.so
的第三方库。我只有老版本的libutils.so
,他的老版本少了一个新版本才有的符号(导出函数)
我可以在新的共享库中编写函数代码(假设 libwrapper.so
):
extern "C" int missing_function() {
return 123;
}
然后……现在??如何“告诉”libfoobar.so
使用此功能,已经尝试过:
- 在
libfoobar.so
之前加载 libwrapper.so
。
- 将 patchelf 工具与
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
(尊重字符数)
- 同时更改 SONAME,在此示例中,将
LIBSUTILS
更改为 LIBUTILX
- 对包装器进行编码并编译为
libutilx.so
。下面的 C 代码示例
- 与
libfoobar.so
和 DONE 放在同一个文件夹中。
#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
干杯
我有一个第三方库(比如 libfoobar.so
)依赖于另一个名为 libutils.so
的第三方库。我只有老版本的libutils.so
,他的老版本少了一个新版本才有的符号(导出函数)
我可以在新的共享库中编写函数代码(假设 libwrapper.so
):
extern "C" int missing_function() {
return 123;
}
然后……现在??如何“告诉”libfoobar.so
使用此功能,已经尝试过:
- 在
libfoobar.so
之前加载libwrapper.so
。 - 将 patchelf 工具与
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
(尊重字符数) - 同时更改 SONAME,在此示例中,将
LIBSUTILS
更改为LIBUTILX
- 对包装器进行编码并编译为
libutilx.so
。下面的 C 代码示例 - 与
libfoobar.so
和 DONE 放在同一个文件夹中。
#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
干杯