'_init'/'_fini' not found - use the compiler drivers

Rod Evans — Tuesday December 19, 2006

Surfing with the Linker-Aliens

A recently added error check within ld(1) has uncovered the following condition.

    ld: warning: symbol `_init' not found, but .init section exists - \\
        possible link-edit without using the compiler driver
    ld: warning: symbol `_fini' not found, but .fini section exists - \\
        possible link-edit without using the compiler driver

The encapsulation, and execution of .init and .fini sections is a combination of user definitions and compiler driver files.

Users typically create these sections using a pragma. For example, the following code produces a .init and .fini section.

    % cat foobar.c
    static int foobar = 0;

    #pragma init (foo)

    void foo()
            foobar = 1;

    #pragma fini (bar)

    void bar()
            foobar = 0;

The functions themselves are placed in a .text section, and a call to foo() is placed in a .init section, and a call to bar() is placed in a .fini section. So, how do these functions get called in the runtime environment?

This is where the compiler drivers come in. As part of creating a dynamic object, the compiler drivers provide input files that encapsulate the .init and .fini calls. This encapsulation effectively creates two functions that are labeled _init and _fini respectively.

    _init {      # provided by .init in crti.o
    call foo()   # provided by .init in foobar.c
    }            # provided by .init in crtn.o

    _fini {      # provided by .init in crti.o
    call bar()   # provided by .init in foobar.c
    }            # provided by .init in crtn.o

It is the symbols _init and _fini that are recognized by ld() and are registered within the object so that the two addresses are called at runtime.

Some folks are using ld() directly to build their shared objects, and thus the encapsulating crt files aren't being included within the link-edit. The result is that even though .init and .fini sections may exist, no _init and _fini encapsulation occurs, and no symbols are registered with the object for runtime execution.

This leaves the developer wondering why their .init and .fini code is never executed, and is the rational behind us adding the warning message.

It's best not to use ld() directly to build any executables or shared objects, let the compiler drivers do it for you.

Surfing with the Linker-Aliens


UX-admin — Wednesday December 20, 2006
What about assembler (.S) files? I'm writing about cranking out straight assembler code directly in a text editor, no C or any high level language involved. How am I supposed to produce an executable out of those?
Rod Evans — Wednesday December 20, 2006

I'm not sure I understand your question.

The point of this posting was to show how the code produced by the compilation system for such things as .init sections, it tied to an encapsulation model provided with files that the compiler drivers deliver.

Regardless of these special sections, you still need a special crt file to provide the standard calling sequence to main(argc, argv).

It is safest to use a compiler driver to generate a final dynamic object.

Surfing with the Linker-Aliens

Published Elsewhere


Surfing with the Linker-Aliens

[25] Displacement Relocation Warnings
Blog Index (rie)
[27] moved /usr/ccs/bin commands