Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receive "undefined symbol" error when loading library with dlopen

I'm writing some code that uses dynamic shared libraries as plugins.

My command line for building the shared libraries looks like:

cc -shared -fPIC -o module.so -g -Wall module.c

Within the module, I can call functions that are in any other shared library that has been loaded within the main executable.

However I cannot access (exported) functions that are in the executable itself (I get undefined symbol errors).

My call to dlopen looks like this:

void *handle = dlopen(plugin, RTLD_NOW);

Can anyone please advise how my module can call back to my executable, without having to put all of the executable's utility functions into yet another shared library?

like image 421
Alnitak Avatar asked Jan 26 '09 17:01

Alnitak


3 Answers

Correct solution is to add -rdynamic to the link command of the main executable. This will add appropriate option to ld (which, when using GNU ld, happens to be --export-dynamic).

Adding --export-dynamic directly is technically incorrect: it's a linker option, and so should be added as -Wl,--export-dynamic, or -Wl,-E. This is also less portable than -rdynamic (other linkers have an equivalent, but the option itself is different).

like image 166
Employed Russian Avatar answered Nov 08 '22 02:11

Employed Russian


I've found the answer myself.

I had to add the --export-dynamic flags to the link options for the main executable.

When creating a dynamically linked executable, add all symbols to the dynamic symbol table. The dynamic symbol table is the set of symbols which are visible from dynamic objects at run time.

If you do not use this option, the dynamic symbol table will normally contain only those symbols which are referenced by some dynamic object mentioned in the link.

If you use "dlopen" to load a dynamic object which needs to refer back to the symbols defined by the program, rather than some other dynamic object, then you will probably need to use this option when linking the program itself.

like image 8
Alnitak Avatar answered Nov 08 '22 02:11

Alnitak


When I encountered the same problem, I just used the following solution. Before loading any plugin, just load the program itself, bringing its symbols to dynamic tables:

dlopen(NULL,RTLD_NOW|RTLD_GLOBAL);

I think the solution is better. The reason is that, it also solves the same problem if you

a) your program (or a trird-party module) is linked (not in runtime) against the shared library, which symbols need to be in dynamic table;

b) can not recompile that module with -rdynamic flag.

like image 4
P Shved Avatar answered Nov 08 '22 01:11

P Shved