I'm using dlopen to load dynamically generated code. The program calls the compiler on the code and generates a .so file which is then loaded by the program to extend itself.
The problem is that if I use the same name for the generated code, the dlopen returns a handle to the old object, not the new one.
The code looks like:
…generate code into test.cpp
system("gcc <args> test.cpp -o test.so");
void *handle = dlopen("test.so");
void *sym = dlsym(handle, "run");
(*sym)();
dlclose(handle);
…Do other work
…generate different code to test.cpp
system("gcc <args> test.cpp -o test.so");
void *handle = dlopen("test.so");
void *sym = dlsym(handle, "run");
(*sym)();
<crash here because the code isn't what was expected>
Is this a basic flaw in dlopen's cache code or something well known and not well documented in dlopen?
Most probly dlclose failed to unload the library. This usually happens when it contains GNU_UNIQUE symbols (which tend to sneak in if you link with static libstdc++). This can be verified via
$ readelf -sW --dyn-syms path/to/libxyz.so | grep '\bUNIQUE\b'
...
3808: 0000000000302e78 8 OBJECT UNIQUE DEFAULT 27 _ZNSt8messagesIcE2idE@@GLIBCXX_3.4
To fix this, you can try one of the following:
- build library with
-fvisibility=hiddenand__attribute__((visibility("default")))to hide unique symbols - build with
-Wl,--version-scriptto achieve the same - build shlib with toolchain that was configured with
--disable-gnu-unique-object(see discussion in GCC list)
来源:https://stackoverflow.com/questions/50437892/dlopen-on-new-binary-with-same-name-returns-old-handle