向使用dlopen打开的共享库提供链接的共享库的符号



考虑以下文件

# Makefile
all: libdyn.so libmain.so app
libdyn.so: libdyn.cpp
g++ -fPIC -shared -o libdyn.so libdyn.cpp
libso.so: libso.cpp
g++ -fPIC -shared -o libso.so libso.cpp
libmain.so: libmain.cpp libso.so
g++ -Wl,--no-as-needed -fPIC -shared -o libmain.so libmain.cpp -ldl -L`pwd` -lso
app: main.cpp   g++ -o app main.cpp -ldl
g++ -o app main.cpp -ldl
// libdyn.cpp
#include <iostream>
extern "C" {
extern void foo();
void bar() {
std::cout << "Calling foo..." << std::endl;
foo();
}
};
// libso.cpp
#include <iostream>
extern "C" {
void foo() {
std::cout << "Hello from foo" << std::endl;
}
};
// libmain.cpp
#include <iostream>
#include <dlfcn.h>
int main_fun() {
void* handle = dlopen("./libdyn.so", RTLD_LAZY);
void (*bar_ptr)() = reinterpret_cast<void(*)()>(dlsym(handle, "bar"));
std::cout << "Calling bar..." << std::endl;
(*bar_ptr)();
return 0;
}
// main.cpp
#include <iostream>
#include <dlfcn.h>
int main() {
void* handle = dlopen("./libmain.so", RTLD_LAZY);
int (*main_fun_ptr)() = reinterpret_cast<int(*)()>(dlsym(handle, "_Z8main_funv"));
std::cout << "Calling main_fun..." << std::endl;
(*main_fun_ptr)(); 
}

调用./app产生

Calling main_fun...
Calling bar...
Calling foo...
./app: symbol lookup error: ./libdyn.so: undefined symbol: foo

CCD_ 2产生

linux-vdso.so.1 (0x00007ffd903f8000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe05cdb8000)
libso.so (0x00007fe05cdb3000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe05cb99000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe05ca4a000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe05ca2f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe05c83b000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe05cddf000)

我不明白为什么libdyn不能访问foolibmain链接到提供foolibso,而libdyn是由libmain加载的,那么不应该找到foo吗?

我对解决这个问题很感兴趣,但也有一些限制。可以怀疑,这是我真正问题的MWE。在我的应用程序中,libmain.so是使用Java Native Interface调用的。此外,只有libmain是用户代码。libsolibdyn是外部库,对我来说很难重新编译,但这是可行的。最后,没有一个foo函数,而是必须以foo的共享方式共享数千个全局变量。

main.cpp中,使用dlopen中的openRTLD_GLOBAL

来自手册:

RTLD_GLOBAL
The  symbols  defined by this shared object will be
made available for symbol resolution
of subsequently loaded shared objects.

编辑:或者,不将libso.so作为依赖项链接到ldd libmain.so0,而是从main_fun:调用dlopen

dlopen("libso.so", RTLD_LAZY|RTLD_GLOBAL)

或者可能来自共享对象初始化器:

static void init(void) __attribute__((constructor));
static void init(void) {
fprintf(stderr, "libmain constructor %s runningn", __func__);
if (!dlopen("libso.so", RTLD_LAZY|RTLD_GLOBAL)) {
fprintf(stderr, "dlopen("libso.so"): *** %sn", dlerror());
exit(1);
}
}

相关内容

  • 没有找到相关文章