Chapter 6. From the Kernel To Stand-Alone Code

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);
int
main (void)
{
	funcptr_t *call_p;
	call_p = &__start_newsect;
	do {
		printf ("call_p: %p\n", call_p);
		(*call_p)();
		++call_p;
	} while (call_p < &__stop_newsect);
	return 0;
}
      

Which generates:

[trevor]$ ./mycalls
call_p: 0x8049488
my_init1() #1
call_p: 0x804948c
my_init2() #2
[trevor]$ 
      

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).