mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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:
parent
414fd31b25
commit
e610499e26
2 changed files with 73 additions and 23 deletions
|
@ -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) */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue