]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kernel: add support for init_array constructors
authorFrantisek Hrbata <fhrbata@redhat.com>
Mon, 14 Oct 2013 07:38:46 +0000 (18:08 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 17 Oct 2013 04:35:17 +0000 (15:05 +1030)
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>
include/asm-generic/vmlinux.lds.h
kernel/module.c

index 83e2c31e8b007528f67f726ec47bc648f24bdda8..bc2121fa9132cc9cad2209cacee3896fdbeb5370 100644 (file)
 #define KERNEL_CTORS() . = ALIGN(8);                      \
                        VMLINUX_SYMBOL(__ctors_start) = .; \
                        *(.ctors)                          \
+                       *(.init_array)                     \
                        VMLINUX_SYMBOL(__ctors_end) = .;
 #else
 #define KERNEL_CTORS()
index 947105fd4cab8863c23be1714b8c27decb09087b..5c9cf84017d52c046f4c9e8b3521171c8da7e402 100644 (file)
@@ -2708,7 +2708,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
        return 0;
 }
 
-static void find_module_sections(struct module *mod, struct load_info *info)
+static int find_module_sections(struct module *mod, struct load_info *info)
 {
        mod->kp = section_objs(info, "__param",
                               sizeof(*mod->kp), &mod->num_kp);
@@ -2738,6 +2738,18 @@ static void find_module_sections(struct module *mod, struct load_info *info)
 #ifdef CONFIG_CONSTRUCTORS
        mod->ctors = section_objs(info, ".ctors",
                                  sizeof(*mod->ctors), &mod->num_ctors);
+       if (!mod->ctors)
+               mod->ctors = section_objs(info, ".init_array",
+                               sizeof(*mod->ctors), &mod->num_ctors);
+       else if (find_sec(info, ".init_array")) {
+               /*
+                * This shouldn't happen with same compiler and binutils
+                * building all parts of the module.
+                */
+               printk(KERN_WARNING "%s: has both .ctors and .init_array.\n",
+                      mod->name);
+               return -EINVAL;
+       }
 #endif
 
 #ifdef CONFIG_TRACEPOINTS
@@ -2776,6 +2788,8 @@ static void find_module_sections(struct module *mod, struct load_info *info)
 
        info->debug = section_objs(info, "__verbose",
                                   sizeof(*info->debug), &info->num_debug);
+
+       return 0;
 }
 
 static int move_module(struct module *mod, struct load_info *info)
@@ -3233,7 +3247,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
        /* Now we've got everything in the final locations, we can
         * find optional sections. */
-       find_module_sections(mod, info);
+       err = find_module_sections(mod, info);
+       if (err)
+               goto free_unload;
 
        err = check_module_license_and_versions(mod);
        if (err)