views:

651

answers:

5

I have a shared library that is linked with another (third-party) shared library. My shared library is then loaded using dlopen in my application. All this works fine (assuming files are in the proper path etc).

Now, the problem is that I don't even need to specify to link against the third-party shared library when I link my library. GCC accept it without reporting errors about undefined references. So, the question; how can I force GCC to notify me about undefined references?

If I change my library to be (temporarily) an executable, I get undefined references (when not supplying the library to the linker). (Works fine if I specify it.)

I.e., the following is done:

g++ -fPIC -shared -o libb.so b.o 
g++ -fPIC -shared -o liba.so a.o
g++ -o a.exe a.cpp 

Where the second line does NOT give out an error and the third line complains about an undefined reference.

Sample code:

a.h:

class a
{
public:
    void foobar();
};

a.cpp:

#include "a.h"
#include "b.h"

void a::foobar()
{
    b myB;
    myB.foobar();
}

int main()
{
    a myA; myA.foobar();
}

b.h:

class b
{
public:
    void foobar();
};

b.cpp:

#include "b.h"

void b::foobar()
{
}
A: 

I dont think you can. That is the problem with dlopen (resolved during runtime).

One way to test it though is to add a target to your Makefile which compiles it like in your a.exe example above. It's a bit of a workaround, but at least that approach lets you catch it at compile time.

Another approach is to create a temporary executable with a main function which just tries to dlopen your so-file.

Martin Wickman
Why is this downvoted? It's a correct answer, and the two suggested approaches works afaik.
Martin Wickman
I think the question isn't about dlopen at all, but when building the shared library itself - which depends upon another shared library.
nos
+2  A: 

You can't make ld (which is what gcc is running) pay attention to a library that isn't there in the link. You can turn off RTLD_LAZY to get agressive reporting, and you can add a unit test that runs right after the link just to flush out these problems.

bmargulies
+5  A: 

-Wl,--no-undefined linker option can be used when building shared library, undefined symbols will be shown as linker errors.

g++ -shared -Wl,-soname,libmylib.so.5 -Wl,--no-undefined -o libmylib.so.1.1 mylib.o -lthirdpartylib

Dmitry Yudakov
Nope, no error at all.
Fredrik Ullner
Could you provide the linker output?
Dmitry Yudakov
Hm, I could've sworn I did this before and didn't get anything as output. Doing this yet again seemed to make this work fine (i.e. I get an error!)
Fredrik Ullner
I edited -Wl,-no-undefined to -Wl,--no-undefined (as ld manual says), although both cases seem to be working for me.
Dmitry Yudakov
+2  A: 

After more research, I realized what way the stuff works. There are two linker options to manipulate undefined symbols of shared libraries:

First one is --no-undefined. It reports the unresolved symbols that are not resolved immediately, at linking stage. Unless the symbol is found in a shared library linked against, either manually (with -l switch) or automatically (libgcc_s, C++ runtime; libc, C runtime; ld-linux-**.so, dynamic linker utils) picked, --no-undefined reports it as error. That's the key the questioner needed.

There is another key, --no-allow-shlib-undefined (whose description also suggests --no-undefined). It checks if definitions in the shared libraries which you link your shared library against are satisfied. This key is of little use in the case shown in this topic, but it can be useful. However, It has its own obstacles.

The manpage provides some rationale about why it's not default:

   --allow-shlib-undefined
   --no-allow-shlib-undefined
       Allows  (the  default)  or  disallows  undefined  symbols  in  shared
       libraries (It is meant, in shared libraries _linked_against_, not the
       one we're creating!--Pavel Shved). This switch is similar to --no-un-
       defined except  that it determines  the  behaviour when the undefined
       symbols are in a shared library rather than a regular object file. It
       does not  affect  how  undefined  symbols in regular object files are
       handled.

       The  reason  that  --allow-shlib-undefined is the default is that the
       shared library being specified at link time may not be  the  same  as
       the one that is available at load time, so the symbols might actually
       be resolvable at load time.  Plus there are some systems,  (eg  BeOS)
       where  undefined  symbols in shared libraries is normal.  (The kernel
       patches them at load time to select which function is most  appropri-
       ate for the current architecture.  This is used for example to dynam-
       ically select an appropriate memset function).  Apparently it is also
       normal for HPPA shared libraries to have undefined symbols.

The thing is that what is said above is also true, for example, for Linux systems, where some of the internal routines of the shared library is implemented in ld-linux.so, the dynamic loader (it's both executable and shared library). Unless you somehow link it, you will get something like this:

/lib64/libc.so.6: undefined reference to `_dl_argv@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `_rtld_global_ro@GLIBC_PRIVATE'
/usr/lib64/gcc/x86_64-suse-linux/4.3/libstdc++.so: undefined reference to `__tls_get_addr@GLIBC_2.3'
/lib64/libc.so.6: undefined reference to `_rtld_global@GLIBC_PRIVATE'
/lib64/libc.so.6: undefined reference to `__libc_enable_secure@GLIBC_PRIVATE'

These are undefined references from the loader, ld-linux.so. It is platform-specific (for example, on my system the correct loader is /lib64/ld-linux-x86-64.so). You may link the loader with your library and check even the tricky references shown above:

g++ -fPIC -shared -o liba.so a.o -Wl,--no-allow-shlib-undefined  /lib64/ld-linux-x86-64.so.2
Pavel Shved
Nope, no error at all regardless if I use --no-allow-shlib-undefined or --no-undefined.
Fredrik Ullner
@Fredrik, I suppose, you forgot to add `-Wl,` stuff. It *does* show error, although *not* the one you wanted. But that's the most you can have.
Pavel Shved
It seems --no-undefined works as expected but --no-allow-shlib-undefined does not. (Working as you say.)
Fredrik Ullner
@Fredrik, thanks. I fixed my totally incorrect post in the way it may be of some use to you.
Pavel Shved
A: 

There's also a good discussion of this at the Mandriva wiki.

David