3

Take a simple example:

void foo() {}

int main()
{
       return 0;
}

I build it and look at the dynamic symbol table:

$ g++ test.cpp -o test
$ nm --dynamic test
0804849c R _IO_stdin_used
         w __gmon_start__
         U __libc_start_main

As expected, I don't see foo. So I build to include unused symbols.

$ gcc test.c -rdynamic -o test
$ nm --dynamic test
0804863c R _IO_stdin_used
         w _Jv_RegisterClasses
0804a010 A __bss_start
0804a008 D __data_start
         w __gmon_start__
080485e0 T __libc_csu_fini
08048570 T __libc_csu_init
         U __libc_start_main
0804a010 A _edata
0804a018 A _end
0804861c T _fini
08048638 R _fp_hw
08048438 T _init
080484a0 T _start
0804a008 W data_start
08048554 T foo
08048559 T main

And you can see that foo is now in the symbol table. Now I build a static version.

$ gcc test.c -rdynamic -static -o test
$ nm --dynamic test
nm: test: No symbols

My symbols have gone, even though I explicitly specified them.

According to the GCC man page:

-static On systems that support dynamic linking, this prevents linking with the shared libraries.

My function foo() is not a shared library.

If I expand this application, and it calls dlopen(), and the library that I load needs to call foo(), my symbol table no longer contains a reference to foo() and my application will fail.

This happened to me recently.

Why does -static negate -rdynamic and how can I work around it?

Community
  • 1
  • 1
Mr Stinky
  • 881
  • 2
  • 11
  • 23
  • What if you compile first: `gcc -c test.c -rdynamic -o test.o`, and then invoke `gcc` to link the app? – Brett Hale Sep 11 '12 at 11:13
  • both `-static` and `-rdynamic` are options for the linker, so it simply becomes `gcc test.o -rdynamic -static -o test`. Same result. – Mr Stinky Sep 11 '12 at 11:27
  • My mistake. replacing `-rdynamic` with `-shared` in compile? – Brett Hale Sep 11 '12 at 11:31
  • I did try the `-shared` earlier when I was looking at the man pages for gcc and ld in depth. It compiles, links, and creates a dynamic symbol table but the application seg faults. – Mr Stinky Sep 11 '12 at 11:36
  • The trick to overcome the seg fault is answered here: http://stackoverflow.com/questions/4963029/executing-a-shared-library-on-unix but this is starting to get away from the original problem. – Mr Stinky Sep 11 '12 at 11:55

1 Answers1

1

I think the idea of an executable statically linked with a C library, but providing exports to a shared library is probably a broken concept. What happens in this case? Let's say your shared library allocates some memory (using it's own copy of the C library) and then passes that to a routine in your executable which frees it (in a different copy of the C library). This smells like a problem. If you need to link some libraries statically, you can use the -Wl,-Bstatic option before those libraries to force linking against the static versions.

Also, if you need more control over what's happening, it might be better to have separate compile and link steps and use ld directly for the link step. It doesn't necessarily help with the command line options that you're using, but I suspect you could land on something that "works" barring the issue mentioned above.

John Szakmeister
  • 44,691
  • 9
  • 89
  • 79
  • Thanks. The core reason I asked this question was to see if I could fix and post a patch for the static native-gdb build option in Crosstool-NG. Like you said, it doesn't make much sense fundamentally. The only way a fully functioning static build of gdb could work is if it was linked to thread_db and remove the dlopen() call. – Mr Stinky Sep 12 '12 at 08:51