aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-01-06 17:41:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-06 18:59:20 -0500
commita06f6211ef9b1785922f9d0e8766d63ac4e66de1 (patch)
tree4ceac7a7eda00cad3b3f02876e75c1c7af41ce23 /kernel/module.c
parent12da3b888b2035bb0f106122f1cc1b6d357fad53 (diff)
module: add within_module_core() and within_module_init()
This series of patches allows kprobes to probe module's __init and __exit functions. This means, you can probe driver initialization and terminating. Currently, kprobes can't probe __init function because these functions are freed after module initialization. And it also can't probe module __exit functions because kprobe increments reference count of target module and user can't unload it. this means __exit functions never be called unless removing probes from the module. To solve both cases, this series of patches introduces GONE flag and sets it when the target code is freed(for this purpose, kprobes hooks MODULE_STATE_* events). This also removes refcount incrementing for allowing user to unload target module. Users can check which probes are GONE by debugfs interface. For taking timing of freeing module's .init text, these also include a patch which adds module's notifier of MODULE_STATE_LIVE event. This patch: Add within_module_core() and within_module_init() for checking whether an address is in the module .init.text section or .text section, and replace within() local inline functions in kernel/module.c with them. kprobes uses these functions to check where the kprobe is inserted. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Acked-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 34b56cf06615..cc79c942c572 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2390,7 +2390,7 @@ static const char *get_ksymbol(struct module *mod,
2390 unsigned long nextval; 2390 unsigned long nextval;
2391 2391
2392 /* At worse, next value is at end of module */ 2392 /* At worse, next value is at end of module */
2393 if (within(addr, mod->module_init, mod->init_size)) 2393 if (within_module_init(addr, mod))
2394 nextval = (unsigned long)mod->module_init+mod->init_text_size; 2394 nextval = (unsigned long)mod->module_init+mod->init_text_size;
2395 else 2395 else
2396 nextval = (unsigned long)mod->module_core+mod->core_text_size; 2396 nextval = (unsigned long)mod->module_core+mod->core_text_size;
@@ -2438,8 +2438,8 @@ const char *module_address_lookup(unsigned long addr,
2438 2438
2439 preempt_disable(); 2439 preempt_disable();
2440 list_for_each_entry_rcu(mod, &modules, list) { 2440 list_for_each_entry_rcu(mod, &modules, list) {
2441 if (within(addr, mod->module_init, mod->init_size) 2441 if (within_module_init(addr, mod) ||
2442 || within(addr, mod->module_core, mod->core_size)) { 2442 within_module_core(addr, mod)) {
2443 if (modname) 2443 if (modname)
2444 *modname = mod->name; 2444 *modname = mod->name;
2445 ret = get_ksymbol(mod, addr, size, offset); 2445 ret = get_ksymbol(mod, addr, size, offset);
@@ -2461,8 +2461,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname)
2461 2461
2462 preempt_disable(); 2462 preempt_disable();
2463 list_for_each_entry_rcu(mod, &modules, list) { 2463 list_for_each_entry_rcu(mod, &modules, list) {
2464 if (within(addr, mod->module_init, mod->init_size) || 2464 if (within_module_init(addr, mod) ||
2465 within(addr, mod->module_core, mod->core_size)) { 2465 within_module_core(addr, mod)) {
2466 const char *sym; 2466 const char *sym;
2467 2467
2468 sym = get_ksymbol(mod, addr, NULL, NULL); 2468 sym = get_ksymbol(mod, addr, NULL, NULL);
@@ -2485,8 +2485,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
2485 2485
2486 preempt_disable(); 2486 preempt_disable();
2487 list_for_each_entry_rcu(mod, &modules, list) { 2487 list_for_each_entry_rcu(mod, &modules, list) {
2488 if (within(addr, mod->module_init, mod->init_size) || 2488 if (within_module_init(addr, mod) ||
2489 within(addr, mod->module_core, mod->core_size)) { 2489 within_module_core(addr, mod)) {
2490 const char *sym; 2490 const char *sym;
2491 2491
2492 sym = get_ksymbol(mod, addr, size, offset); 2492 sym = get_ksymbol(mod, addr, size, offset);
@@ -2705,7 +2705,7 @@ int is_module_address(unsigned long addr)
2705 preempt_disable(); 2705 preempt_disable();
2706 2706
2707 list_for_each_entry_rcu(mod, &modules, list) { 2707 list_for_each_entry_rcu(mod, &modules, list) {
2708 if (within(addr, mod->module_core, mod->core_size)) { 2708 if (within_module_core(addr, mod)) {
2709 preempt_enable(); 2709 preempt_enable();
2710 return 1; 2710 return 1;
2711 } 2711 }