I like the linux kernel module_init function very much, I would like to implement the same function for my user space applications.
I try to modify the linker script to do this:
1, copy a x86-64 standard ld script
2, add my customized section
.module.init : { PROVIDE_HIDDEN (__module_init_start = .); *(.module_init*) PROVIDE_HIDDEN (__module_init_end = .); }
3, put the init function pointer into moudle_init section
#define app_module_init(x) __initcall(x); #define __initcall(fn) static initcall_t __initcall_##fn __attribute__ ((__section__(".module_init"))) = fn app_module_init(unit_test_1_init); app_module_init(unit_test_2_init); app_module_init(unit_test_3_init); app_module_init(unit_test_4_init);
4, compile the app with a customized linker script(based on the standard one)
gcc -o "./module_init" -T module.lds ./module_init.o
5, Then I objdump the moudle_init, I found the section is generated:
Disassembly of section .module_init: 0000000000a01080 <__initcall_unit_test_1_init>: a01080: ad lods %ds:(%rsi),%eax a01081: 05 40 00 00 00 add $0x40,%eax ... 0000000000a01088 <__initcall_unit_test_2_init>: a01088: c2 05 40 retq $0x4005 a0108b: 00 00 add %al,(%rax) a0108d: 00 00 add %al,(%rax) ... 0000000000a01090 <__initcall_unit_test_3_init>: a01090: d7 xlat %ds:(%rbx) a01091: 05 40 00 00 00 add $0x40,%eax ... 0000000000a01098 <__initcall_unit_test_4_init>: a01098: ec in (%dx),%al a01099: 05 40 00 00 00 add $0x40,%eax
But the __module_init_start and __module_init_end variable is not the value I expected. In my case __module_init_start is 0x4005ad and __module_init_end is 0x400000003. This is very weird, because 0x4005ad is the address of __initcall_unit_test_1_init.
Anyone can give me an idea on how to make this user space module_init work?
Advertisement
Answer
The linker script can only set the addresses of variables. Use &__module_init_start
to get a pointer to the start of the section, and &__module_init_end
to get a pointer to the end.