Commit b99b87f70c7785ab1e253c6220f4b0b57ce3a7f7
Committed by
Linus Torvalds
1 parent
e24aca672f
Exists in
master
and in
20 other branches
kernel: constructor support
Call constructors (gcc-generated initcall-like functions) during kernel start and module load. Constructors are e.g. used for gcov data initialization. Disable constructor support for usermode Linux to prevent conflicts with host glibc. Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Acked-by: Rusty Russell <rusty@rustcorp.com.au> Acked-by: WANG Cong <xiyou.wangcong@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Jeff Dike <jdike@addtoit.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Huang Ying <ying.huang@intel.com> Cc: Li Wei <W.Li@Sun.COM> Cc: Michael Ellerman <michaele@au1.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Heiko Carstens <heicars2@linux.vnet.ibm.com> Cc: Martin Schwidefsky <mschwid2@linux.vnet.ibm.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 7 changed files with 54 additions and 0 deletions Side-by-side Diff
include/asm-generic/sections.h
... | ... | @@ -14,6 +14,9 @@ |
14 | 14 | extern char __initdata_begin[], __initdata_end[]; |
15 | 15 | extern char __start_rodata[], __end_rodata[]; |
16 | 16 | |
17 | +/* Start and end of .ctors section - used for constructor calls. */ | |
18 | +extern char __ctors_start[], __ctors_end[]; | |
19 | + | |
17 | 20 | /* function descriptor handling (if any). Override |
18 | 21 | * in asm/sections.h */ |
19 | 22 | #ifndef dereference_function_descriptor |
include/asm-generic/vmlinux.lds.h
... | ... | @@ -440,12 +440,21 @@ |
440 | 440 | INIT_TASK \ |
441 | 441 | } |
442 | 442 | |
443 | +#ifdef CONFIG_CONSTRUCTORS | |
444 | +#define KERNEL_CTORS() VMLINUX_SYMBOL(__ctors_start) = .; \ | |
445 | + *(.ctors) \ | |
446 | + VMLINUX_SYMBOL(__ctors_end) = .; | |
447 | +#else | |
448 | +#define KERNEL_CTORS() | |
449 | +#endif | |
450 | + | |
443 | 451 | /* init and exit section handling */ |
444 | 452 | #define INIT_DATA \ |
445 | 453 | *(.init.data) \ |
446 | 454 | DEV_DISCARD(init.data) \ |
447 | 455 | CPU_DISCARD(init.data) \ |
448 | 456 | MEM_DISCARD(init.data) \ |
457 | + KERNEL_CTORS() \ | |
449 | 458 | *(.init.rodata) \ |
450 | 459 | DEV_DISCARD(init.rodata) \ |
451 | 460 | CPU_DISCARD(init.rodata) \ |
include/linux/init.h
... | ... | @@ -134,6 +134,9 @@ |
134 | 134 | extern initcall_t __con_initcall_start[], __con_initcall_end[]; |
135 | 135 | extern initcall_t __security_initcall_start[], __security_initcall_end[]; |
136 | 136 | |
137 | +/* Used for contructor calls. */ | |
138 | +typedef void (*ctor_fn_t)(void); | |
139 | + | |
137 | 140 | /* Defined in init/main.c */ |
138 | 141 | extern int do_one_initcall(initcall_t fn); |
139 | 142 | extern char __initdata boot_command_line[]; |
include/linux/module.h
init/Kconfig
init/main.c
... | ... | @@ -720,6 +720,17 @@ |
720 | 720 | rest_init(); |
721 | 721 | } |
722 | 722 | |
723 | +/* Call all constructor functions linked into the kernel. */ | |
724 | +static void __init do_ctors(void) | |
725 | +{ | |
726 | +#ifdef CONFIG_CONSTRUCTORS | |
727 | + ctor_fn_t *call = (ctor_fn_t *) __ctors_start; | |
728 | + | |
729 | + for (; call < (ctor_fn_t *) __ctors_end; call++) | |
730 | + (*call)(); | |
731 | +#endif | |
732 | +} | |
733 | + | |
723 | 734 | int initcall_debug; |
724 | 735 | core_param(initcall_debug, initcall_debug, bool, 0644); |
725 | 736 | |
... | ... | @@ -800,6 +811,7 @@ |
800 | 811 | usermodehelper_init(); |
801 | 812 | driver_init(); |
802 | 813 | init_irq_proc(); |
814 | + do_ctors(); | |
803 | 815 | do_initcalls(); |
804 | 816 | } |
805 | 817 |
kernel/module.c
... | ... | @@ -2216,6 +2216,10 @@ |
2216 | 2216 | mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings, |
2217 | 2217 | "__kcrctab_unused_gpl"); |
2218 | 2218 | #endif |
2219 | +#ifdef CONFIG_CONSTRUCTORS | |
2220 | + mod->ctors = section_objs(hdr, sechdrs, secstrings, ".ctors", | |
2221 | + sizeof(*mod->ctors), &mod->num_ctors); | |
2222 | +#endif | |
2219 | 2223 | |
2220 | 2224 | #ifdef CONFIG_MARKERS |
2221 | 2225 | mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers", |
... | ... | @@ -2389,6 +2393,17 @@ |
2389 | 2393 | goto free_hdr; |
2390 | 2394 | } |
2391 | 2395 | |
2396 | +/* Call module constructors. */ | |
2397 | +static void do_mod_ctors(struct module *mod) | |
2398 | +{ | |
2399 | +#ifdef CONFIG_CONSTRUCTORS | |
2400 | + unsigned long i; | |
2401 | + | |
2402 | + for (i = 0; i < mod->num_ctors; i++) | |
2403 | + mod->ctors[i](); | |
2404 | +#endif | |
2405 | +} | |
2406 | + | |
2392 | 2407 | /* This is where the real work happens */ |
2393 | 2408 | SYSCALL_DEFINE3(init_module, void __user *, umod, |
2394 | 2409 | unsigned long, len, const char __user *, uargs) |
... | ... | @@ -2417,6 +2432,7 @@ |
2417 | 2432 | blocking_notifier_call_chain(&module_notify_list, |
2418 | 2433 | MODULE_STATE_COMING, mod); |
2419 | 2434 | |
2435 | + do_mod_ctors(mod); | |
2420 | 2436 | /* Start the module */ |
2421 | 2437 | if (mod->init != NULL) |
2422 | 2438 | ret = do_one_initcall(mod->init); |