diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/kernel/module.c b/kernel/module.c index cabafe228444..f3cba93ea1e3 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -117,6 +117,8 @@ struct load_info { | |||
117 | char *secstrings, *strtab; | 117 | char *secstrings, *strtab; |
118 | unsigned long *strmap; | 118 | unsigned long *strmap; |
119 | unsigned long symoffs, stroffs; | 119 | unsigned long symoffs, stroffs; |
120 | struct _ddebug *debug; | ||
121 | unsigned int num_debug; | ||
120 | struct { | 122 | struct { |
121 | unsigned int sym, str, mod, vers, info, pcpu; | 123 | unsigned int sym, str, mod, vers, info, pcpu; |
122 | } index; | 124 | } index; |
@@ -1993,7 +1995,7 @@ static void layout_symtab(struct module *mod, struct load_info *info) | |||
1993 | mod->core_size += bitmap_weight(info->strmap, strsect->sh_size); | 1995 | mod->core_size += bitmap_weight(info->strmap, strsect->sh_size); |
1994 | } | 1996 | } |
1995 | 1997 | ||
1996 | static void add_kallsyms(struct module *mod, struct load_info *info) | 1998 | static void add_kallsyms(struct module *mod, const struct load_info *info) |
1997 | { | 1999 | { |
1998 | unsigned int i, ndst; | 2000 | unsigned int i, ndst; |
1999 | const Elf_Sym *src; | 2001 | const Elf_Sym *src; |
@@ -2040,6 +2042,8 @@ static void add_kallsyms(struct module *mod, struct load_info *info) | |||
2040 | 2042 | ||
2041 | static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num) | 2043 | static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num) |
2042 | { | 2044 | { |
2045 | if (!debug) | ||
2046 | return; | ||
2043 | #ifdef CONFIG_DYNAMIC_DEBUG | 2047 | #ifdef CONFIG_DYNAMIC_DEBUG |
2044 | if (ddebug_add_module(debug, num, debug->modname)) | 2048 | if (ddebug_add_module(debug, num, debug->modname)) |
2045 | printk(KERN_ERR "dynamic debug error adding module: %s\n", | 2049 | printk(KERN_ERR "dynamic debug error adding module: %s\n", |
@@ -2267,8 +2271,7 @@ static int check_modinfo(struct module *mod, struct load_info *info) | |||
2267 | return 0; | 2271 | return 0; |
2268 | } | 2272 | } |
2269 | 2273 | ||
2270 | static void find_module_sections(struct module *mod, | 2274 | static void find_module_sections(struct module *mod, struct load_info *info) |
2271 | const struct load_info *info) | ||
2272 | { | 2275 | { |
2273 | mod->kp = section_objs(info, "__param", | 2276 | mod->kp = section_objs(info, "__param", |
2274 | sizeof(*mod->kp), &mod->num_kp); | 2277 | sizeof(*mod->kp), &mod->num_kp); |
@@ -2323,9 +2326,15 @@ static void find_module_sections(struct module *mod, | |||
2323 | &mod->num_ftrace_callsites); | 2326 | &mod->num_ftrace_callsites); |
2324 | #endif | 2327 | #endif |
2325 | 2328 | ||
2329 | mod->extable = section_objs(info, "__ex_table", | ||
2330 | sizeof(*mod->extable), &mod->num_exentries); | ||
2331 | |||
2326 | if (section_addr(info, "__obsparm")) | 2332 | if (section_addr(info, "__obsparm")) |
2327 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", | 2333 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", |
2328 | mod->name); | 2334 | mod->name); |
2335 | |||
2336 | info->debug = section_objs(info, "__verbose", | ||
2337 | sizeof(*info->debug), &info->num_debug); | ||
2329 | } | 2338 | } |
2330 | 2339 | ||
2331 | static int move_module(struct module *mod, struct load_info *info) | 2340 | static int move_module(struct module *mod, struct load_info *info) |
@@ -2512,6 +2521,20 @@ static void module_deallocate(struct module *mod, struct load_info *info) | |||
2512 | module_free(mod, mod->module_core); | 2521 | module_free(mod, mod->module_core); |
2513 | } | 2522 | } |
2514 | 2523 | ||
2524 | static int post_relocation(struct module *mod, const struct load_info *info) | ||
2525 | { | ||
2526 | sort_extable(mod->extable, mod->extable + mod->num_exentries); | ||
2527 | |||
2528 | /* Copy relocated percpu area over. */ | ||
2529 | percpu_modcopy(mod, (void *)info->sechdrs[info->index.pcpu].sh_addr, | ||
2530 | info->sechdrs[info->index.pcpu].sh_size); | ||
2531 | |||
2532 | add_kallsyms(mod, info); | ||
2533 | |||
2534 | /* Arch-specific module finalizing. */ | ||
2535 | return module_finalize(info->hdr, info->sechdrs, mod); | ||
2536 | } | ||
2537 | |||
2515 | /* Allocate and load the module: note that size of section 0 is always | 2538 | /* Allocate and load the module: note that size of section 0 is always |
2516 | zero, and we rely on this for optional sections. */ | 2539 | zero, and we rely on this for optional sections. */ |
2517 | static noinline struct module *load_module(void __user *umod, | 2540 | static noinline struct module *load_module(void __user *umod, |
@@ -2521,8 +2544,6 @@ static noinline struct module *load_module(void __user *umod, | |||
2521 | struct load_info info = { NULL, }; | 2544 | struct load_info info = { NULL, }; |
2522 | struct module *mod; | 2545 | struct module *mod; |
2523 | long err; | 2546 | long err; |
2524 | struct _ddebug *debug = NULL; | ||
2525 | unsigned int num_debug = 0; | ||
2526 | 2547 | ||
2527 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", | 2548 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
2528 | umod, len, uargs); | 2549 | umod, len, uargs); |
@@ -2564,22 +2585,7 @@ static noinline struct module *load_module(void __user *umod, | |||
2564 | if (err < 0) | 2585 | if (err < 0) |
2565 | goto free_modinfo; | 2586 | goto free_modinfo; |
2566 | 2587 | ||
2567 | /* Set up and sort exception table */ | 2588 | err = post_relocation(mod, &info); |
2568 | mod->extable = section_objs(&info, "__ex_table", | ||
2569 | sizeof(*mod->extable), &mod->num_exentries); | ||
2570 | sort_extable(mod->extable, mod->extable + mod->num_exentries); | ||
2571 | |||
2572 | /* Finally, copy percpu area over. */ | ||
2573 | percpu_modcopy(mod, (void *)info.sechdrs[info.index.pcpu].sh_addr, | ||
2574 | info.sechdrs[info.index.pcpu].sh_size); | ||
2575 | |||
2576 | add_kallsyms(mod, &info); | ||
2577 | |||
2578 | if (!mod->taints) | ||
2579 | debug = section_objs(&info, "__verbose", | ||
2580 | sizeof(*debug), &num_debug); | ||
2581 | |||
2582 | err = module_finalize(info.hdr, info.sechdrs, mod); | ||
2583 | if (err < 0) | 2589 | if (err < 0) |
2584 | goto free_modinfo; | 2590 | goto free_modinfo; |
2585 | 2591 | ||
@@ -2607,8 +2613,9 @@ static noinline struct module *load_module(void __user *umod, | |||
2607 | goto unlock; | 2613 | goto unlock; |
2608 | } | 2614 | } |
2609 | 2615 | ||
2610 | if (debug) | 2616 | /* This has to be done once we're sure module name is unique. */ |
2611 | dynamic_debug_setup(debug, num_debug); | 2617 | if (!mod->taints) |
2618 | dynamic_debug_setup(info.debug, info.num_debug); | ||
2612 | 2619 | ||
2613 | /* Find duplicate symbols */ | 2620 | /* Find duplicate symbols */ |
2614 | err = verify_export_symbols(mod); | 2621 | err = verify_export_symbols(mod); |
@@ -2640,7 +2647,8 @@ static noinline struct module *load_module(void __user *umod, | |||
2640 | /* Unlink carefully: kallsyms could be walking list. */ | 2647 | /* Unlink carefully: kallsyms could be walking list. */ |
2641 | list_del_rcu(&mod->list); | 2648 | list_del_rcu(&mod->list); |
2642 | ddebug: | 2649 | ddebug: |
2643 | dynamic_debug_remove(debug); | 2650 | if (!mod->taints) |
2651 | dynamic_debug_remove(info.debug); | ||
2644 | unlock: | 2652 | unlock: |
2645 | mutex_unlock(&module_mutex); | 2653 | mutex_unlock(&module_mutex); |
2646 | synchronize_sched(); | 2654 | synchronize_sched(); |