From: Peter Oberparleiter 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 Acked-by: Rusty Russell Acked-by: WANG Cong Cc: Sam Ravnborg Cc: Jeff Dike --- include/asm-generic/sections.h | 3 +++ include/asm-generic/vmlinux.lds.h | 11 ++++++++++- include/linux/init.h | 3 +++ include/linux/module.h | 6 ++++++ init/Kconfig | 5 +++++ init/main.c | 12 ++++++++++++ kernel/module.c | 16 ++++++++++++++++ 7 files changed, 55 insertions(+), 1 deletion(-) Index: linux-2.6.30-rc5/include/asm-generic/vmlinux.lds.h =================================================================== --- linux-2.6.30-rc5.orig/include/asm-generic/vmlinux.lds.h +++ linux-2.6.30-rc5/include/asm-generic/vmlinux.lds.h @@ -332,6 +332,14 @@ /* Section used for early init (in .S files) */ #define HEAD_TEXT *(HEAD_TEXT_SECTION) +#ifdef CONFIG_CONSTRUCTORS +#define KERNEL_CTORS() VMLINUX_SYMBOL(__ctors_start) = .; \ + *(.ctors) \ + VMLINUX_SYMBOL(__ctors_end) = .; +#else +#define KERNEL_CTORS() +#endif + /* init and exit section handling */ #define INIT_DATA \ *(.init.data) \ @@ -340,7 +348,8 @@ CPU_DISCARD(init.data) \ CPU_DISCARD(init.rodata) \ MEM_DISCARD(init.data) \ - MEM_DISCARD(init.rodata) + MEM_DISCARD(init.rodata) \ + KERNEL_CTORS() #define INIT_TEXT \ *(.init.text) \ Index: linux-2.6.30-rc5/include/linux/init.h =================================================================== --- linux-2.6.30-rc5.orig/include/linux/init.h +++ linux-2.6.30-rc5/include/linux/init.h @@ -136,6 +136,9 @@ typedef void (*exitcall_t)(void); extern initcall_t __con_initcall_start[], __con_initcall_end[]; extern initcall_t __security_initcall_start[], __security_initcall_end[]; +/* Used for contructor calls. */ +typedef void (*ctor_fn_t)(void); + /* Defined in init/main.c */ extern int do_one_initcall(initcall_t fn); extern char __initdata boot_command_line[]; Index: linux-2.6.30-rc5/include/linux/module.h =================================================================== --- linux-2.6.30-rc5.orig/include/linux/module.h +++ linux-2.6.30-rc5/include/linux/module.h @@ -354,6 +354,12 @@ struct module local_t ref; #endif #endif + +#ifdef CONFIG_CONSTRUCTORS + /* Constructor functions. */ + ctor_fn_t *ctors; + unsigned int num_ctors; +#endif }; #ifndef MODULE_ARCH_INIT #define MODULE_ARCH_INIT {} Index: linux-2.6.30-rc5/init/main.c =================================================================== --- linux-2.6.30-rc5.orig/init/main.c +++ linux-2.6.30-rc5/init/main.c @@ -700,6 +700,17 @@ asmlinkage void __init start_kernel(void rest_init(); } +/* Call all constructor functions linked into the kernel. */ +static void __init do_ctors(void) +{ +#ifdef CONFIG_CONSTRUCTORS + ctor_fn_t *call = (ctor_fn_t *) __ctors_start; + + for (; call < (ctor_fn_t *) __ctors_end; call++) + (*call)(); +#endif +} + int initcall_debug; core_param(initcall_debug, initcall_debug, bool, 0644); @@ -780,6 +791,7 @@ static void __init do_basic_setup(void) usermodehelper_init(); driver_init(); init_irq_proc(); + do_ctors(); do_initcalls(); } Index: linux-2.6.30-rc5/kernel/module.c =================================================================== --- linux-2.6.30-rc5.orig/kernel/module.c +++ linux-2.6.30-rc5/kernel/module.c @@ -2172,6 +2172,10 @@ static noinline struct module *load_modu sizeof(*mod->tracepoints), &mod->num_tracepoints); #endif +#ifdef CONFIG_CONSTRUCTORS + mod->ctors = section_objs(hdr, sechdrs, secstrings, ".ctors", + sizeof(*mod->ctors), &mod->num_ctors); +#endif #ifdef CONFIG_MODVERSIONS if ((mod->num_syms && !mod->crcs) @@ -2328,6 +2332,17 @@ static noinline struct module *load_modu goto free_hdr; } +/* Call module constructors. */ +static void do_mod_ctors(struct module *mod) +{ +#ifdef CONFIG_CONSTRUCTORS + unsigned long i; + + for (i = 0; i < mod->num_ctors; i++) + mod->ctors[i](); +#endif +} + /* This is where the real work happens */ SYSCALL_DEFINE3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs) @@ -2356,6 +2371,7 @@ SYSCALL_DEFINE3(init_module, void __user blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod); + do_mod_ctors(mod); /* Start the module */ if (mod->init != NULL) ret = do_one_initcall(mod->init); Index: linux-2.6.30-rc5/init/Kconfig =================================================================== --- linux-2.6.30-rc5.orig/init/Kconfig +++ linux-2.6.30-rc5/init/Kconfig @@ -16,6 +16,11 @@ config DEFCONFIG_LIST default "$ARCH_DEFCONFIG" default "arch/$ARCH/defconfig" +config CONSTRUCTORS + bool + depends on !UML + default y + menu "General setup" config EXPERIMENTAL Index: linux-2.6.30-rc5/include/asm-generic/sections.h =================================================================== --- linux-2.6.30-rc5.orig/include/asm-generic/sections.h +++ linux-2.6.30-rc5/include/asm-generic/sections.h @@ -14,6 +14,9 @@ extern char __kprobes_text_start[], __kp extern char __initdata_begin[], __initdata_end[]; extern char __start_rodata[], __end_rodata[]; +/* Start and end of .ctors section - used for constructor calls. */ +extern char __ctors_start[], __ctors_end[]; + /* function descriptor handling (if any). Override * in asm/sections.h */ #ifndef dereference_function_descriptor -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/