diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2003-01-05 04:08:01 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-01-05 04:08:01 -0800 |
| commit | af285fc8b5eec2a2b6695c7e2d0a1842dbd1c059 (patch) | |
| tree | d630f5ad07e7585ad17cb796188a54681eb3d8ce /kernel | |
| parent | 3344ea3ad4b7c302c846a680dbaeedf96ed45c02 (diff) | |
[PATCH] Exception table cleanup
This patch combines the common exception table searching functionality
for various architectures, to avoid unneccessary (and currently buggy)
duplication, and so that the exception table list and lock can be kept
private to module.c.
The archs provide "struct exception_table" and "search_extable": the
generic infrastructure drives the rest.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/extable.c | 42 | ||||
| -rw-r--r-- | kernel/module.c | 56 |
2 files changed, 62 insertions, 36 deletions
diff --git a/kernel/extable.c b/kernel/extable.c index 4e9055ba6bb8..b980aa1d52d7 100644 --- a/kernel/extable.c +++ b/kernel/extable.c @@ -16,45 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/module.h> -#include <linux/init.h> - -#include <asm/semaphore.h> extern const struct exception_table_entry __start___ex_table[]; extern const struct exception_table_entry __stop___ex_table[]; -extern const struct kernel_symbol __start___ksymtab[]; -extern const struct kernel_symbol __stop___ksymtab[]; -extern const struct kernel_symbol __start___gpl_ksymtab[]; -extern const struct kernel_symbol __stop___gpl_ksymtab[]; - -/* Protects extables and symbol tables */ -spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED; - -/* The exception and symbol tables: start with kernel only. */ -LIST_HEAD(extables); -LIST_HEAD(symbols); -static struct exception_table kernel_extable; -static struct kernel_symbol_group kernel_symbols; -static struct kernel_symbol_group kernel_gpl_symbols; - -void __init extable_init(void) +/* Given an address, look for it in the exception tables. */ +const struct exception_table_entry *search_exception_tables(unsigned long addr) { - /* Add kernel symbols to symbol table */ - kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab); - kernel_symbols.syms = __start___ksymtab; - kernel_symbols.gplonly = 0; - list_add(&kernel_symbols.list, &symbols); - kernel_gpl_symbols.num_syms = (__stop___gpl_ksymtab - - __start___gpl_ksymtab); - kernel_gpl_symbols.syms = __start___gpl_ksymtab; - kernel_gpl_symbols.gplonly = 1; - list_add(&kernel_gpl_symbols.list, &symbols); + const struct exception_table_entry *e; - /* Add kernel exception table to exception tables */ - kernel_extable.num_entries = (__stop___ex_table -__start___ex_table); - kernel_extable.entry = __start___ex_table; - list_add(&kernel_extable.list, &extables); + e = search_extable(__start___ex_table, __stop___ex_table-1, addr); + if (!e) + e = search_module_extables(addr); + return e; } - - diff --git a/kernel/module.c b/kernel/module.c index cd005fb850af..ba3520523d78 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -51,9 +51,14 @@ #define symbol_is(literal, string) \ (strcmp(MODULE_SYMBOL_PREFIX literal, (string)) == 0) +/* Protects extables and symbols lists */ +static spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED; + /* List of modules, protected by module_mutex */ static DECLARE_MUTEX(module_mutex); -LIST_HEAD(modules); /* FIXME: Accessed w/o lock on oops by some archs */ +LIST_HEAD(modules); /* FIXME: Accessed w/o lock on oops by some archs */ +static LIST_HEAD(symbols); +static LIST_HEAD(extables); /* We require a truly strong try_module_get() */ static inline int strong_try_module_get(struct module *mod) @@ -1425,6 +1430,55 @@ struct seq_operations modules_op = { .show = m_show }; +/* Given an address, look for it in the module exception tables. */ +const struct exception_table_entry *search_module_extables(unsigned long addr) +{ + unsigned long flags; + const struct exception_table_entry *e = NULL; + struct exception_table *i; + + spin_lock_irqsave(&modlist_lock, flags); + list_for_each_entry(i, &extables, list) { + if (i->num_entries == 0) + continue; + + e = search_extable(i->entry, i->entry+i->num_entries-1, addr); + if (e) + break; + } + spin_unlock_irqrestore(&modlist_lock, flags); + + /* Now, if we found one, we are running inside it now, hence + we cannot unload the module, hence no refcnt needed. */ + return e; +} + +/* Provided by the linker */ +extern const struct kernel_symbol __start___ksymtab[]; +extern const struct kernel_symbol __stop___ksymtab[]; +extern const struct kernel_symbol __start___gpl_ksymtab[]; +extern const struct kernel_symbol __stop___gpl_ksymtab[]; + +static struct kernel_symbol_group kernel_symbols, kernel_gpl_symbols; + +static int __init symbols_init(void) +{ + /* Add kernel symbols to symbol table */ + kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab); + kernel_symbols.syms = __start___ksymtab; + kernel_symbols.gplonly = 0; + list_add(&kernel_symbols.list, &symbols); + kernel_gpl_symbols.num_syms = (__stop___gpl_ksymtab + - __start___gpl_ksymtab); + kernel_gpl_symbols.syms = __start___gpl_ksymtab; + kernel_gpl_symbols.gplonly = 1; + list_add(&kernel_gpl_symbols.list, &symbols); + + return 0; +} + +__initcall(symbols_init); + /* Obsolete lvalue for broken code which asks about usage */ int module_dummy_usage = 1; EXPORT_SYMBOL(module_dummy_usage); |
