I have an application that is loading some plugins via dlopen
, specifically dlopen(name, RTLD_LAZY|RTLD_DEEPBIND)
. There are some plugins (provided in binary form) that load fine, but the plugin I am trying to build fails to load with an error:
/opt/app/plugins/plugin.so: undefined symbol: Log_Modules
All the plugins refer to that symbol, and the library that provides it is loaded in the process. However the entry printed by objdump -D
differs. In the plugins that load it says
00000000 DO *UND* 00000000 Log_Modules
and in the library defining it it says
000130dc g DO .data 00000004 Base Log_Modules
while in the module I built it says
00000000 D *UND* 00000000 Log_Modules
The manual page of objdump
just says that the flag means
The symbol is the name of a function (F) or a file (f) or an object (O) or just a normal symbol (a space).
but I don't see any hint for what the difference between an object and normal symbol is. So
what is the difference
The O
flag corresponds to the STT_OBJECT
flag, signifying an object, that is a variable.
what makes the symbol one or the other at the C or C++ language or linker level
Apparently, the linker marks symbols with the STT_OBJECT
flag only if it actually sees the definition, i.e. when the library that defines it is provided as a dependency. Extern declarations alone are not marked.
is it indeed supposed to make the symbol not resolve?
When resolving symbols, the linker looks in explicitly listed dependencies, and libraries loaded with RTLD_GLOBAL
, which includes the dependencies of the main executable. So when the main executable already happens to link the defining library, the plugin will get away with not linking it explicitly, but if it is itself loaded with dlopen
(without RTLD_GLOBAL
), it won't.
The absence of the flag itself isn't the problem, but it hints at the actual problem of missing library reference.