Я хочу загрузить разделяемую библиотеку с помощью dlopen
и сделать так, чтобы символы в ней были доступны без необходимости индивидуального захвата указателей на функции с помощью dlsym
.Страница man говорит, что флаг 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);
}
creation.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