我想用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
函数覆盖test()
的main
函数,但事实并非如此。我知道我也可以将main()
中的所有代码移动到另一个共享库run
然后main()
dlopen
libimplementation.so
与RTLD_GLOBAL
然后让librun.so
引用libimplementation.so
中的符号而不定义它们以便加载它们:
修改main.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);
}
run.c:
#include <stdio.h>
int is_loaded(void);
void run(void){
puts(is_loaded() ? "Implementation loaded" : "Implementation not loaded");
}
并且Makefile
获得librun.so
作为all
的先决条件。
有没有办法在没有dlsym
的情况下从共享库中获取符号,或者将实际代码放在另一个共享库中,例如librun.so
?
从根本上没有办法做你想要的。想象一下主程序有:
static char *myptr = array_in_lib1;
后来,在你dlopen
时,myptr
还有其他价值。程序刚刚将变量更改为指向不同的对象吗?或者它是否已经增加以指向数组中的某个元素 - 在这种情况下,您是否希望将其调整为使用新打开的库中的新定义来重新定义array_in_lib1
?或者它只是一个随机整数投射到char *
?如果不了解程序员的意图以及它如何到达当前状态的完整过程历史,决定如何对待它是不可能的。
以上是我构建的一个特别令人震惊的例子,但是符号在运行时改变定义的想法在各种方面都是根本不一致的。甚至RTLD_DEEPBIND
,它已经做了,可以说是不和谐和错误。无论你想做什么,你都应该找到另一种方法。