Search code examples
cglobal-variablesshared-librariesexterndlopen

Handling global variables in shared object


I have some global variable defined in global.c file as below:

int globalvar;

I have a header file global.h that declares this variable as extern

extern int globalVar;

Now I have main.c that gets linked with compiled global.o (compiled from global.c) having code to open (using dlopen) a shared object sh.so that gets built from sh.c with access to globalVar, through global.h. Although, my executable has definition of globalVar (statically linked), when I load the dynamically linked library sh.so, it says undefined globalVar. How to handle this?


Solution

  • Although, my executable has definition of globalVar (statically linked), when I load the dynamically linked library sh.so, it says undefined globalVar.

    This is expected. An ELF binary has two symbol tables: a regular one and one used for dynamic linking. You can examine them like so:

     nm    a.out | grep globalVar  # expected: address D globalVar
     nm -D a.out | grep globalVar  # expected: no output
    

    The reason linker doesn't put globalVar into the dynamic symbol table is that (at link time) nothing outside of the binary needs that symbol.

    How to handle this?

    There are a few ways.

    1. If you add -rdynamic to your link line, you'll be asking the linker to export every defined symbol into the dynamic symbol table. While in general this is a a bad idea, it's the fastest way to solve your problem here.
    2. If you use Gold to link, you can use -Wl,--export-dynamic-symbol=globalVar to export just the globalVar
    3. You can use -Wl,--dynamic-list=globals.txt and put globalVar into the globals.txt file.
    4. You can use -Wl,--dynamic-list-data to export all global data variables (this is only slightly better than -rdynamic).