Linker and Libraries Guide

Weak Symbols

Weak symbol references that are not bound during a link-edit will not result in a fatal error condition, no matter what output file type is being generated.

If a static executable is being generated, the symbol will be converted to an absolute symbol and assigned a value of zero.

If a dynamic executable or shared object is being produced, the symbol will be left as an undefined weak reference. During process execution, the runtime linker will search for this symbol, and if it does not find a match, will bind the reference to an address of zero instead of generating a fatal runtime relocation error.

Historically, these undefined weak referenced symbols have been employed as a mechanism for testing for the existence of functionality. For example, the following C code fragment may have been used in the shared object libfoo.so.1:


#pragma weak    foo
 
extern  void    foo(char *);
 
void
bar(char * path)
{
        void (* fptr)();
 
        if ((fptr = foo) != 0)
                (* fptr)(path);
}

When an application is built that references libfoo.so.1, the link-edit will successfully complete regardless of whether a definition for the symbol foo is found. If, during execution of the application the function address tests nonzero, the function will be called. However, if the symbol definition is not found, the function address will test zero, and so will not be called.

However, compilation systems view this address comparison technique as having undefined semantics, which can result in the test statement being removed under optimization. In addition, the runtime symbol binding mechanism places other restrictions on the use of this technique which prevents a consistent model from being available for all dynamic objects.

Users are discouraged from using undefined weak references in this manner, and instead are encouraged to use dlsym(3X) with the RTLD_DEFAULT flag as a means of testing for a symbols existence (see "Testing for Functionality").