Search code examples
gccshared-librariesldelf

What makes a symbol in an ELF library an object or normal one?


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,
  • what makes the symbol one or the other at the C or C++ language or linker level and
  • is it indeed supposed to make the symbol not resolve?

Solution

  • 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.