What we have discovered is not just an understanding of how the Linux kernel works, but also a solution for creating a compile-time list of function pointers which call be called in the order they are initialized. Taking the code from the previous section and making it more stand-alone and general purpose we end up with the following: (notice how no linker script is required)

 * Copyright (C) 2006  Trevor Woerner

#include <stdio.h>

typedef void (*funcptr_t)(void);
extern funcptr_t __start_newsect, __stop_newsect;

#define data_attr         __attribute__ ((section ("newsect")))
#define create_entry(fn)  funcptr_t _##fn data_attr = fn

void my_init1 (void) { printf ("my_init1() #1\n"); }
void my_init2 (void) { printf ("my_init2() #2\n"); }

create_entry (my_init1);
create_entry (my_init2);

main (void)
        funcptr_t *call_p;

        call_p = &__start_newsect;
        do {
                printf ("call_p: %p\n", call_p);
        } while (call_p < &__stop_newsect);

        return 0;

Which generates:

[trevor@trevor code]$ make mycalls   
cc     mycalls.c   -o mycalls
[trevor@trevor code]$ ./mycalls 
call_p: 0x804960c
my_init1() #1
call_p: 0x8049610
my_init2() #2


0804830c g     F .text  00000000              _start
0804830c l    d  .text  00000000              .text
08048330 l     F .text  00000000              call_gmon_start
08048354 l     F .text  00000000              __do_global_dtors_aux
08048388 l     F .text  00000000              frame_dummy
080483b0 g     F .text  00000018              my_init1
080483c8 g     F .text  00000018              my_init2
080483e0 g     F .text  00000053              main
08048434 g     F .text  0000004f              __libc_csu_init
08048484 g     F .text  00000005              __libc_csu_fini
0804848c l     F .text  00000000              __do_global_ctors_aux
0804960c g       *ABS*  00000000              __start_newsect
0804960c g     O newsect        00000004              _my_init1
0804960c l    d  newsect        00000000              newsect
08049610 g     O newsect        00000004              _my_init2
08049614 g       *ABS*  00000000              __bss_start
08049614 g       *ABS*  00000000              __stop_newsect

Notice also how the my_initN() functions were put in the general .text segment since I don't really care where they end up (unlike the kernel guys).

KernelNewbies: InitcallMechanism/KernelToCode (last edited 2017-12-30 01:29:57 by localhost)