Deferred Binding of Function Pointers in SHLIB

Roland McGrath roland@hack.frob.com
Fri Jan 1 00:00:00 GMT 2016


I think you are confused about what you're observing.  Lazy binding
happens only for PLT entries, i.e. for direct function calls.  There
is never lazy binding for data initializers like your example uses.

Your use of -Wl,--unresolved-symbols=ignore-all means that the
non-shared case (libmain.c as executable) is simply mis-linked.  (If
you remove that switch, then the link will fail to complete and you
can never get a binary to run.)  After linking it's as if you'd
instead had "void (*func_p)(void) = 0;" in the source.  No kind of
binding at all happens at runtime.  The reason you saw the output
from printf is because there was no kind of symbol resolution
happening at all, and so nothing to fail at startup--your program
starts up fine, does what it does, and only crashes when it tries to
call the function pointer with value 0.

In the shared library case, foo is left undefined in the DSO.  The
same would happen without --unresolved-symbols=ignore-all.  (To see
link-time checking for apparent definedness of referenced symbols,
use -Wl,-z,defs.)  Because the reference to foo is in a data
initializer rather than a PLT entry (i.e., what you'd get if main
had the line "foo();"), it has to be resolved at startup time by the
dynamic linker before any of your code runs at all.  Since that
resolution fails, the dynamic linker bails out before even trying to
start your program.



More information about the Gnu-gabi mailing list