Linker and Libraries Guide

Initialization and Termination Sections

The .init and .fini section types provide for runtime initialization and termination processing. These section types are concatenated from the input relocatable objects like any other sections. However, the compiler drivers can also supply .init and .fini sections as part of the additional files they add to the beginning and end of your input-file list.

These files have the effect of encapsulating the .init and .fini code into individual functions that are identified by the reserved symbol names _init and _fini respectively.

When building a dynamic executable or shared object, the link-editor records these symbol addresses in the output file's image so they can be called by the runtime linker during initialization and termination processing. See "Initialization and Termination Routines" for more details on the runtime processing of these sections.

The creation of .init and .fini sections can be carried out directly using an assembler, or some compilers can offer special primitives to simplify their declaration. For example, the following code segments result in a call to the function foo being placed in an .init section, and a call to the function bar being placed in a .fini section:


#pragma init (foo)
#pragma fini (bar)
 
foo()
{
    /* Perform some initialization processing. */
    ......
}
 
bar()
{
    /* Perform some termination processing. */
    .......
}

Be careful when designing initialization and termination code that can be included in both a shared object and archive library. If this code is spread throughout several relocatable objects within an archive library, then the link-edit of an application using this archive can extract only a portion of the modules, and therefore only a portion of the initialization and termination code. At runtime, only this portion of code is executed.

The same application built against the shared object will have all the accumulated initialization and termination code executed at runtime when the shared object is mapped in as one of the application's dependencies.

It is also recommended that data initialization be independent if the .init code is involved with a dynamic object whose memory can be dumped using dldump(3X).