I have a DSO (mylibrary.so.0
library) with a func1
function marked as extern "C"
and which I'm sure it's exported since
nm -D mylibrary.so.0 | grep func1
000000000009f9bb T func1 <- symbol is visible and exported
This DSO is being loaded in a chain of dependencies I have no control over, e.g.
executable1 -dlopen-> 3rdpartydispatcher.so -dlopen-> my_library.so.0
Now, my library has a method which gets called (I can see it's getting called by stepping into it via gdb) and receives a C string with the function name it should call, e.g.
void call_function_from_name(const char *function_name) {
void *mylibrary_so_0 = dlopen(NULL, RTLD_NOW); // (*)
void *func1 = dlsym(mylibrary_so_0, function_name);
if (!func1) {
log_error(dlerror());
}
...
}
The problem is: even if call_function_from_name
is being called with argument func1
, i.e. a perfectly valid and exported symbol, dlsym
is failing and the error is executable1 has no func1 symbol
.
I come from a Windows environment and I assumed that dlopen(NULL, ..)
returns me a handle on the main executable but that any subsequent dlopen
'd library from that executable gets also mapped in its virtual address space and therefore I can use that handle to search for the symbols those libraries exported.
Is my assumption incorrect? If it is, how can I refer to func1
from within a same-dso function call?
`void *mylibrary_so_0 = dlopen(NULL, RTLD_NOW); // (*)`
For some reason you believe that this should dlopen
my_library.so.0
, but it doesn't -- it opens the main executable.
The error message clearly tells you that: executable1 has no func1
.
A possible fix is use dlopen("my_library.so.0", RTLD_NOW)
, but a much better fix it to provide a static map of functions you want to be able to call this way, and use that:
struct mapping { const char *f_name; void (*f_ptr)(); } = {
{ "func1", &func1 },
{ "func2", &func2 },
{ NULL, NULL },
};
Now just search your mapping
, and call the target function; no dlsym
required.