Force Gcc to Notify About Undefined References in Shared Libraries

Force GCC to notify about undefined references in shared libraries

-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

What is the g++ flag that permits undefined references in shared libraries?

This can only be a linker flag... and then, it depends on what linker you're using.

On Linux (and probably BSD, at least FreeBSD) this should be the default behaviour. Not on Mac though.

From the GNU ld man page:

--allow-shlib-undefined
--no-allow-shlib-undefined
Allows or disallows undefined symbols in shared libraries.
This switch is similar to --no-undefined 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 default behaviour is to report errors for any undefined symbols
referenced in shared libraries if the linker is being used to create an
executable, but to allow them if the linker is being used to create a
shared library.

From the Apple ld man page:

-undefined treatment  
Specifies how undefined symbols are to be treated. Options
are: error, warning, suppress, or dynamic_lookup. The
default is error.

How to make linker fail for undefined references when building shared library in Linux

When I'm building and want to avoid this situation, I compile the library with the options: -Wl,--no-allow-shlib-undefined -Wl,-z,defs

The first option causes the link of the shared library to fail in the situation that a symbol is not defined in the code, when used in combination with the second option, which causes the linker to report the missing symbols.

This works well to prevent missing symbols at run-time by detecting them at link time. I do, however, need to link the .so with all the libraries it uses, as otherwise it will fail to build.

sample (src.c):

#include <math.h>

extern
double share_the_stuff(double val)
{
return acos(val * val);
}

Build with missing symbol:

gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs
/usr/bin/ld: /tmp/ccFmD5uY.o: in function `share_the_stuff':
src.c:(.text+0x17): undefined reference to `acos'
collect2: error: ld returned 1 exit status

link in libm.so:

gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs -lm

It behaves the same with missing internal symbols.

Can GCC not complain about undefined references?

Yes, it is possible to avoid reporting undefined references - using --unresolved-symbols linker option.

g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files

From man ld

--unresolved-symbols=method

Determine how to handle unresolved symbols. There are four
possible values for method:

       ignore-all
Do not report any unresolved symbols.

report-all
Report all unresolved symbols. This is the default.

ignore-in-object-files
Report unresolved symbols that are contained in shared
libraries, but ignore them if they come from regular object
files.

ignore-in-shared-libs
Report unresolved symbols that come from regular object
files, but ignore them if they come from shared libraries. This
can be useful when creating a dynamic binary and it is known
that all the shared libraries that it should be referencing
are included on the linker's command line.

The behaviour for shared libraries on their own can also be
controlled by the --[no-]allow-shlib-undefined option.

Normally the linker will generate an error message for each
reported unresolved symbol but the option --warn-unresolved-symbols can
change this to a warning.

Undefined reference from shared library in static one

Static libraries are just an agglomeration of object files (their members), perhaps with a ranlib(1) generated index.

On Linux, if you link an object file (3) foo.o with a static library (2) libee.a and a shared library (1) libyz.so and if you pass -rdynamic at link time (i.e. gcc -rdynamic foo.o libee.a libyz.so -o myprog or gcc -rdynamic foo.o -lee -lyz -o myprog) then dynamic linker would resolve the get_object name at dynamic link time (in ld-linux.so)

Details are explained in ELF wikipage and Drepper's paper: How To Write Shared Libraries. Read also Levine's book: Linkers and loaders & ld(1) man page.

Why does g++ detect undefined reference when dynamically linking

With the ELF format it indeed isn't necessary to know which symbols belong to which library, as the actual symbol resolution happens when the program is executed. By convention though ld will still resolve the symbols when producing the binary. It's for your convenience, so that you get immediate feedback when you have missing symbols, since in that case the chance is big your program won't work.

Using the --warn-unresolved-symbols flag you can change ld behavior in this case from an error to a warning:

$ g++ -Wl,--warn-unresolved-symbols main.cpp -lusertest

Should emit a warning but still create the executable. Note that you still need to provide the library name, otherwise ld won't know where to look for the needed symbols.

On Windows, the linker needs to know exactly which symbol belongs to which library in order to produce the necessary import tables. So it is impossible to build a PE binary with unresolved symbols.

Easy check for unresolved symbols in shared libraries?

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


Related Topics



Leave a reply



Submit