3

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?

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69

2 Answers2

4

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).
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
-1

More as an explanation than a solution (I am not an expert in Linux shared libraries), in both the global.o and sh.so only the addresses of the variables and functions of their own unit are known.

So, to let a shared library know the location of a global variable in your executable, you must tell the dynamic library where to find it, i.e. what its address is. In the same way, when you want to call a function in a dynamic library, you must request the library for its address.

The link of Antti Haapala, How can a shared library (.so) call a function that is implemented in its loader program?, shows how to do this.

Community
  • 1
  • 1
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • This explanation is mostly wrong. Certainly you can call `open` in main executable, and find the definition of `open` in `libc.so` *without* doing anything special. – Employed Russian Apr 30 '17 at 18:36
  • @Employed Russion, maybe you can find the definition (show me how???) but you can't access it because you don't know its adress. You'll _have_ to do domething special, either you, the libraries or the compiler. – Paul Ogilvie May 01 '17 at 05:49
  • You forgot the linker and the dynamic loader, which conspire to make this all work. In any case, your explanation implies that the programmer has to do something "to find the definition", which is clearly not the case. – Employed Russian May 01 '17 at 06:04