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