Accessing .So Libraries Using Dlopen() Throws Undefined Symbol Error

Accessing .so libraries using dlopen() throws undefined symbol error

Most likely, libCamera.so uses a symbol defined in a shared library without depending on that library.

  1. Find a culprit. Take a real executable which links against libCamera.so (and it works). List its dependencies with ldd /path/to/executable. Among them should be a library which has a definition for ZTVN10_cxxabiv117__class_type_infoE (use grep to select likely candidates, nm -D on a library to be sure). That library won't be in the list shown by ldd ./libCamera.so.

  2. Solve a problem. Load the library found in step 1 by dlopen first (use RTLD_GLOBAL there as well).

  3. If there is a problem with another symbol, goto step 1.

  4. If newly-added libraries have the same problem too, goto step 1.

  5. Tell library authors to please fix their linking.

It could also happen that one of the prerequisites in ldd ./libCamera.so got upgraded and lost a symbol definition (maybe it was recompiled with a compiler which does name mangling differently). Then you won't find the culprit in step 1, and there is no solution but downgrading something again.

C++ linux: dlopen can't find .so library

Read the dlopen(3) man page (e.g. by typing man dlopen in a terminal on your machine):

If filename contains a slash ("/"), then it
is interpreted as a (relative or absolute) pathname. Otherwise, the
dynamic linker searches for the library as follows (see ld.so(8) for
further details):

   o   (ELF only) If the executable file for the calling program
contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag,
then the directories listed in the DT_RPATH tag are searched.

o If, at the time that the program was started, the environment
variable LD_LIBRARY_PATH was defined to contain a colon-separated
list of directories, then these are searched. (As a security
measure this variable is ignored for set-user-ID and set-group-ID
programs.)

o (ELF only) If the executable file for the calling program
contains a DT_RUNPATH tag, then the directories listed in that
tag are searched.

o The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is
checked to see whether it contains an entry for filename.

o The directories /lib and /usr/lib are searched (in that order).

So you need to call dlopen("./libLibraryName.so", RTLD_NOW) -not just dlopen("libLibraryName.so", RTLD_NOW) which wants your plugin to be in your $LD_LIBRARY_PATH on in /usr/lib/ etc .... - or add . to your LD_LIBRARY_PATH (which I don't recommend for security reasons).

As Jhonnash answered you should use and display the result of dlerror when dlopen (or dlsym) fails:

  void* dlh = dlopen("./libLibraryName.so", RTLD_NOW);
if (!dlh)
{ fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit(EXIT_FAILURE); };

You might want to read some books like Advanced Linux Programming to get some knowledge about Linux system programming in general.

Import c-modules from embedded Python interpreter (pybind11) in a shared object raises an undefined symbol exception

I've found a solution. Knowing that it was not tied to numpy halped quite a lot to switch the focus on the real problem: symbol missing. Taking the suggestion from this answer and in particular this point:

Solve a problem. Load the library found in step 1 by dlopen first (use RTLD_GLOBAL there as well).

I've modified the minimum example as follows:

// main.cc
#include "pybind11/embed.h"
#include <dlfcn.h>
namespace py = pybind11;

extern "C" {
void * python;

int create() {
python = dlopen("/usr/lib/x86_64-linux-gnu/libpython3.8.so", RTLD_NOW | RTLD_GLOBAL);
return 0;
}

int destroy() {
dlclose(python);
return 0;
}

int main() {
py::scoped_interpreter guard{};
auto py_module = py::module::import("numpy");
auto version = py_module.attr("__version__");
py::print(version);
return 0;
}
}
// load.cc
#include <dlfcn.h>

int main() {
void * lib = dlopen("./libissue.so", RTLD_NOW | RTLD_DEEPBIND);
int(*fnc)(void) = (int(*)(void))dlsym(lib, "main");
int(*create)(void) = (int(*)(void))dlsym(lib, "create");
int(*destroy)(void) = (int(*)(void))dlsym(lib, "destroy");
create();
fnc();
destroy();
dlclose(lib);
return 0;
}

(obviously in cmake I had to add ${CMAKE_DL_LIBS} as target link library for issue target).

Using Qt5 in a library

Ok I found the solution. Since I use different folders for the header and the source files, I have to manually specify where is the file containing the qt code.

QT5_WRAP_CPP( MOCS_HDRS ${INCLUDE_DIR}/UIWindow.h )

Linker error while working with dynamic class loading in C++

You defined vector<polygon> t; in main.cpp, which will make it to link against polygon's ctor/dtor, that's the link error.

To resolve the issue:

  1. Either follow @robert's answer to directly link polygon.cpp
  2. Or avoid use the complete type of polygon in your main.cpp.

So you should define vector<polygon*> t; instead, and push/pop polygon* to/from the vector.

And you should not forget to call destroy_triangle() when you pop from the vector, otherwise you have memory leak.



Related Topics



Leave a reply



Submit