我想使用dlopen
加载共享库并在其中使用符号,而不必使用dlsym
单独获取指向它们的函数指针。 man page表示RTLD_DEEPBIND
标志将在全局范围之前的库中查找符号,但这显然并不意味着它会覆盖现有符号,因为这不起作用。考虑以下示例:
main.c:
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
int is_loaded(){return 0;}
int main(){
void *h = dlopen("./libimplementation.so", RTLD_NOW | RTLD_DEEPBIND);
if(!h){
printf("Could not load implementation: %s\n", dlerror());
return 1;
}
puts(is_loaded() ? "Implementation loaded" : "Implementation not loaded");
dlclose(h);
}
implementation.c:
int is_loaded(){return 1;}
Makefile:
all: main libimplementation.so
main: main.c
gcc -Wall -std=c99 -o $@ $^ -ldl
lib%.so: %.c
gcc -Wall -std=c99 -o $@ $^ -shared
clean:
-rm main *.so
当我使用make
和./main
进行构建和运行时,我期望test()
中的libimplementation.so
函数会覆盖{{1}中的test()
函数},但事实并非如此。我知道我也可以将main
中的所有代码移到另一个共享库main()
中,然后将run
main()
dlopen
与libimplementation.so
一起使用,并然后让RTLD_GLOBAL
引用librun.so
中的符号而不定义它们,以便加载它们:
修改过的main.c:
libimplementation.so
run.c:
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
int main(){
void *impl_h = dlopen("./libimplementation.so", RTLD_LAZY | RTLD_GLOBAL);
if(!impl_h){
printf("Could not load implementation: %s\n", dlerror());
return 1;
}
void *run_h = dlopen("./librun.so", RTLD_LAZY);
if(!run_h){
printf("Could not load run: %s\n", dlerror());
dlclose(impl_h);
return 1;
}
void (*run)(void);
*(void**)&run = dlsym(run_h, "run");
if(!*(void**)&run){
printf("Could not find entry point in run: %s\n", dlerror());
dlclose(impl_h);
dlclose(run_h);
return 1;
}
run();
dlclose(impl_h);
dlclose(run_h);
}
,并且#include <stdio.h>
int is_loaded(void);
void run(void){
puts(is_loaded() ? "Implementation loaded" : "Implementation not loaded");
}
被添加Makefile
作为librun.so
的前提。
有没有一种方法可以立即从共享库中获取符号,而无需使用all
或将实际代码放入dlsym
这样的另一个共享库中?
答案 0 :(得分:2)
从根本上讲,您无法做任何您想做的事情。想象一下主程序有这样的东西:
static char *myptr = array_in_lib1;
后来,在您dlopen
时,myptr
还有其他价值。程序是否刚刚将变量更改为指向其他对象?还是增加了它以指向数组中稍后的某个元素-在这种情况下,您是否要对其进行调整以使用新打开的库中的新定义来说明对array_in_lib1
的重新定义?还是只是随机整数转换为char *
?在不了解程序员如何达到当前状态的程序员意图 和完整过程历史记录的情况下,决定如何进行处理是不可能的。
以上是我构建的一个极其出色的示例,但是在运行时更改符号定义的想法在各种方面根本上是不一致的。甚至RTLD_DEEPBIND
都已经被认为是不稳定的和有问题的。无论您想做什么,都应该找到另一种方式。