module: __module_address

Impact: New API, cleanup

ksplice wants to know the bounds of a module, not just the module text.

It makes sense to have __module_address.  We then implement
is_module_address and __module_text_address in terms of this (and
change is_module_text_address() to bool while we're at it).

Also, add proper kerneldoc for them all.

Cc: Anders Kaseorg <andersk@mit.edu>
Cc: Jeff Arnold <jbarnold@mit.edu>
Cc: Tim Abbott <tabbott@mit.edu>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2009-03-31 13:05:31 -06:00
parent 414fd31b25
commit e610499e26
2 changed files with 73 additions and 23 deletions

View file

@ -365,7 +365,9 @@ static inline int module_is_live(struct module *mod)
/* Is this address in a module? (second is with no locks, for oops) */ /* Is this address in a module? (second is with no locks, for oops) */
struct module *module_text_address(unsigned long addr); struct module *module_text_address(unsigned long addr);
struct module *__module_text_address(unsigned long addr); struct module *__module_text_address(unsigned long addr);
int is_module_address(unsigned long addr); struct module *__module_address(unsigned long addr);
bool is_module_address(unsigned long addr);
bool is_module_text_address(unsigned long addr);
static inline int within_module_core(unsigned long addr, struct module *mod) static inline int within_module_core(unsigned long addr, struct module *mod)
{ {
@ -494,21 +496,29 @@ search_module_extables(unsigned long addr)
return NULL; return NULL;
} }
/* Is this address in a module? */
static inline struct module *module_text_address(unsigned long addr) static inline struct module *module_text_address(unsigned long addr)
{ {
return NULL; return NULL;
} }
/* Is this address in a module? (don't take a lock, we're oopsing) */ static inline struct module *__module_address(unsigned long addr)
{
return NULL;
}
static inline struct module *__module_text_address(unsigned long addr) static inline struct module *__module_text_address(unsigned long addr)
{ {
return NULL; return NULL;
} }
static inline int is_module_address(unsigned long addr) static inline bool is_module_address(unsigned long addr)
{ {
return 0; return false;
}
static inline bool is_module_text_address(unsigned long addr)
{
return false;
} }
/* Get/put a kernel symbol (calls should be symmetric) */ /* Get/put a kernel symbol (calls should be symmetric) */

View file

@ -76,7 +76,7 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq);
static BLOCKING_NOTIFIER_HEAD(module_notify_list); static BLOCKING_NOTIFIER_HEAD(module_notify_list);
/* Bounds of module allocation, for speeding __module_text_address */ /* Bounds of module allocation, for speeding __module_address */
static unsigned long module_addr_min = -1UL, module_addr_max = 0; static unsigned long module_addr_min = -1UL, module_addr_max = 0;
int register_module_notifier(struct notifier_block * nb) int register_module_notifier(struct notifier_block * nb)
@ -2745,29 +2745,31 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
} }
/* /*
* Is this a valid module address? * is_module_address - is this address inside a module?
* @addr: the address to check.
*
* See is_module_text_address() if you simply want to see if the address
* is code (not data).
*/ */
int is_module_address(unsigned long addr) bool is_module_address(unsigned long addr)
{ {
struct module *mod; bool ret;
preempt_disable(); preempt_disable();
ret = __module_address(addr) != NULL;
list_for_each_entry_rcu(mod, &modules, list) {
if (within_module_core(addr, mod)) {
preempt_enable();
return 1;
}
}
preempt_enable(); preempt_enable();
return 0; return ret;
} }
/*
/* Is this a valid kernel address? */ * __module_address - get the module which contains an address.
__notrace_funcgraph struct module *__module_text_address(unsigned long addr) * @addr: the address.
*
* Must be called with preempt disabled or module mutex held so that
* module doesn't get freed during this.
*/
__notrace_funcgraph struct module *__module_address(unsigned long addr)
{ {
struct module *mod; struct module *mod;
@ -2775,12 +2777,50 @@ __notrace_funcgraph struct module *__module_text_address(unsigned long addr)
return NULL; return NULL;
list_for_each_entry_rcu(mod, &modules, list) list_for_each_entry_rcu(mod, &modules, list)
if (within(addr, mod->module_init, mod->init_text_size) if (within_module_core(addr, mod)
|| within(addr, mod->module_core, mod->core_text_size)) || within_module_init(addr, mod))
return mod; return mod;
return NULL; return NULL;
} }
/*
* is_module_text_address - is this address inside module code?
* @addr: the address to check.
*
* See is_module_address() if you simply want to see if the address is
* anywhere in a module. See kernel_text_address() for testing if an
* address corresponds to kernel or module code.
*/
bool is_module_text_address(unsigned long addr)
{
bool ret;
preempt_disable();
ret = __module_text_address(addr) != NULL;
preempt_enable();
return ret;
}
/*
* __module_text_address - get the module whose code contains an address.
* @addr: the address.
*
* Must be called with preempt disabled or module mutex held so that
* module doesn't get freed during this.
*/
struct module *__module_text_address(unsigned long addr)
{
struct module *mod = __module_address(addr);
if (mod) {
/* Make sure it's within the text section. */
if (!within(addr, mod->module_init, mod->init_text_size)
&& !within(addr, mod->module_core, mod->core_text_size))
mod = NULL;
}
return mod;
}
struct module *module_text_address(unsigned long addr) struct module *module_text_address(unsigned long addr)
{ {
struct module *mod; struct module *mod;