Linker and Libraries Guide

Weak Symbols

Weak symbol references that are not bound during a link-edit do 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 is 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 searches for this symbol, and if it does not find a match, binds 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 to test for the existence of functionality. For example, the following C code fragment might 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 complete successfully regardless of whether a definition for the symbol foo is found. If, during execution of the application, the function address tests nonzero, the function is called. However, if the symbol definition is not found, the function address tests zero, and so is not 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.

Undefined weak references in this manner are discouraged; instead, use dlsym(3X) with the RTLD_DEFAULT flag as a means of testing for a symbols existence (see "Testing for Functionality").