Commit b99b87f70c7785ab1e253c6220f4b0b57ce3a7f7

Authored by Peter Oberparleiter
Committed by Linus Torvalds
1 parent e24aca672f

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
... ... @@ -363,6 +363,12 @@
363 363 local_t ref;
364 364 #endif
365 365 #endif
  366 +
  367 +#ifdef CONFIG_CONSTRUCTORS
  368 + /* Constructor functions. */
  369 + ctor_fn_t *ctors;
  370 + unsigned int num_ctors;
  371 +#endif
366 372 };
367 373 #ifndef MODULE_ARCH_INIT
368 374 #define MODULE_ARCH_INIT {}
... ... @@ -16,6 +16,11 @@
16 16 default "$ARCH_DEFCONFIG"
17 17 default "arch/$ARCH/defconfig"
18 18  
  19 +config CONSTRUCTORS
  20 + bool
  21 + depends on !UML
  22 + default y
  23 +
19 24 menu "General setup"
20 25  
21 26 config EXPERIMENTAL
... ... @@ -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  
... ... @@ -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);