Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kernel: add support for init_array constructors

This adds the .init_array section as yet another section with constructors. This
is needed because gcc could add __gcov_init calls to .init_array or .ctors
section, depending on gcc (and binutils) version .

v2: - reuse mod->ctors for .init_array section for modules, because gcc uses
.ctors or .init_array, but not both at the same time
v3: - fail to load if that does happen somehow.

Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

authored by

Frantisek Hrbata and committed by
Rusty Russell
eb3057df eed380f3

+19 -2
+1
include/asm-generic/vmlinux.lds.h
··· 473 473 #define KERNEL_CTORS() . = ALIGN(8); \ 474 474 VMLINUX_SYMBOL(__ctors_start) = .; \ 475 475 *(.ctors) \ 476 + *(.init_array) \ 476 477 VMLINUX_SYMBOL(__ctors_end) = .; 477 478 #else 478 479 #define KERNEL_CTORS()
+18 -2
kernel/module.c
··· 2708 2708 return 0; 2709 2709 } 2710 2710 2711 - static void find_module_sections(struct module *mod, struct load_info *info) 2711 + static int find_module_sections(struct module *mod, struct load_info *info) 2712 2712 { 2713 2713 mod->kp = section_objs(info, "__param", 2714 2714 sizeof(*mod->kp), &mod->num_kp); ··· 2738 2738 #ifdef CONFIG_CONSTRUCTORS 2739 2739 mod->ctors = section_objs(info, ".ctors", 2740 2740 sizeof(*mod->ctors), &mod->num_ctors); 2741 + if (!mod->ctors) 2742 + mod->ctors = section_objs(info, ".init_array", 2743 + sizeof(*mod->ctors), &mod->num_ctors); 2744 + else if (find_sec(info, ".init_array")) { 2745 + /* 2746 + * This shouldn't happen with same compiler and binutils 2747 + * building all parts of the module. 2748 + */ 2749 + printk(KERN_WARNING "%s: has both .ctors and .init_array.\n", 2750 + mod->name); 2751 + return -EINVAL; 2752 + } 2741 2753 #endif 2742 2754 2743 2755 #ifdef CONFIG_TRACEPOINTS ··· 2788 2776 2789 2777 info->debug = section_objs(info, "__verbose", 2790 2778 sizeof(*info->debug), &info->num_debug); 2779 + 2780 + return 0; 2791 2781 } 2792 2782 2793 2783 static int move_module(struct module *mod, struct load_info *info) ··· 3247 3233 3248 3234 /* Now we've got everything in the final locations, we can 3249 3235 * find optional sections. */ 3250 - find_module_sections(mod, info); 3236 + err = find_module_sections(mod, info); 3237 + if (err) 3238 + goto free_unload; 3251 3239 3252 3240 err = check_module_license_and_versions(mod); 3253 3241 if (err)