Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easy check for unresolved symbols in shared libraries?

I am writing a fairly large C++ shared-object library, and have run into a small issue that makes debugging a pain:

If I define a function/method in a header file, and forget to create a stub for it (during development), since I am building as a shared object library rather than an executable, no errors appear at compile-time telling me I have forgotten to implement that function. The only way I find out something is wrong is at runtime, when eventually an application linking against this library falls over with an 'undefined symbol' error.

I am looking for an easy way to check if I have all the symbols I need at compile time, perhaps something I can add to my Makefile.

One solution I did come up with is to run the compiled library through nm -C -U to get a demangled list of all undefined references. The problem is this also comes up with the list of all references that are in other libraries, such as GLibC, which of course will be linked against along with this library when the final application is put together. It would be possible to use the output of nm to grep through all my header files and see if any of the names corresponding.. but this seems insane. Surely this is not an uncommon issue and there is a better way of solving it?

like image 792
David Claridge Avatar asked Oct 24 '09 07:10

David Claridge


People also ask

Can a static library have unresolved symbols?

At link time, a static library can have unresolved symbols in it, as long as you don't need the unresolved symbols, and you don't need any symbol that is in a .o file that contains an unresolved symbol.

What is unresolved external symbol error in C?

The unresolved external symbol is a linker error that indicates it cannot find the symbol or its reference during the linking process.

What does U mean in Nm output?

An undefined symbol is a symbol that the library uses but was not defined in any of the object files that went into creating the library. Usually the symbol is defined in another library which also needs to be linked in to your application.


1 Answers

Check out the linker option -z defs / --no-undefined. When creating a shared object, it will cause the link to fail if there are unresolved symbols.

If you are using gcc to invoke the linker, you'll use the compiler -Wl option to pass the option to the linker:

gcc -shared ... -Wl,-z,defs 

As an example, consider the following file:

#include <stdio.h>  void forgot_to_define(FILE *fp);  void doit(const char *filename) {     FILE *fp = fopen(filename, "r");     if (fp != NULL)     {         forgot_to_define(fp);         fclose(fp);     } } 

Now, if you build that into a shared object, it will succeed:

> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed succeeded 

But if you add -z defs, the link will fail and tell you about your missing symbol:

> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed /tmp/cccIwwbn.o: In function `doit': silly.c:(.text+0x2c): undefined reference to `forgot_to_define' collect2: ld returned 1 exit status failed 
like image 137
R Samuel Klatchko Avatar answered Sep 17 '22 00:09

R Samuel Klatchko