diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2017-06-19 17:59:43 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2017-06-19 18:05:54 +1000 |
commit | 86c9927ddfd6aa521783a7ec69633c8a10c8d00a (patch) | |
tree | f562e4720072a0c7eed7f3ab85f4ea2195b8ab4c | |
parent | b981c3b08f2cabef786ba168b80b6db67d9004ef (diff) | |
download | linux-next-86c9927ddfd6aa521783a7ec69633c8a10c8d00a.tar.gz |
Revert "lib/extable.c: use bsearch() library function in search_extable()"
This reverts commit 222785199d50099d847bd4b0613e3b0eb22e8d5e.
-rw-r--r-- | include/linux/extable.h | 3 | ||||
-rw-r--r-- | kernel/extable.c | 2 | ||||
-rw-r--r-- | kernel/module.c | 2 | ||||
-rw-r--r-- | lib/extable.c | 38 |
4 files changed, 22 insertions, 23 deletions
diff --git a/include/linux/extable.h b/include/linux/extable.h index b575bb9b5285..7effea4b257d 100644 --- a/include/linux/extable.h +++ b/include/linux/extable.h @@ -2,14 +2,13 @@ #define _LINUX_EXTABLE_H #include <linux/stddef.h> /* for NULL */ -#include <linux/types.h> struct module; struct exception_table_entry; const struct exception_table_entry * search_extable(const struct exception_table_entry *first, - const size_t num, + const struct exception_table_entry *last, unsigned long value); void sort_extable(struct exception_table_entry *start, struct exception_table_entry *finish); diff --git a/kernel/extable.c b/kernel/extable.c index 78604baab401..0fbdd8582f08 100644 --- a/kernel/extable.c +++ b/kernel/extable.c @@ -55,7 +55,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr) { const struct exception_table_entry *e; - e = search_extable(__start___ex_table, __stop___ex_table - __start___ex_table, addr); + 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 065032b734d2..e3e9dbba6a5b 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -4211,7 +4211,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) goto out; e = search_extable(mod->extable, - mod->num_exentries, + mod->extable + mod->num_exentries - 1, addr); out: preempt_enable(); diff --git a/lib/extable.c b/lib/extable.c index 4f84fe1f57f3..62968daa66a9 100644 --- a/lib/extable.c +++ b/lib/extable.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/bsearch.h> #include <linux/module.h> #include <linux/init.h> #include <linux/sort.h> @@ -52,7 +51,7 @@ static void swap_ex(void *a, void *b, int size) * This is used both for the kernel exception table and for * the exception tables of modules that get loaded. */ -static int cmp_ex_sort(const void *a, const void *b) +static int cmp_ex(const void *a, const void *b) { const struct exception_table_entry *x = a, *y = b; @@ -68,7 +67,7 @@ void sort_extable(struct exception_table_entry *start, struct exception_table_entry *finish) { sort(start, finish - start, sizeof(struct exception_table_entry), - cmp_ex_sort, swap_ex); + cmp_ex, swap_ex); } #ifdef CONFIG_MODULES @@ -94,20 +93,6 @@ void trim_init_extable(struct module *m) #endif /* !ARCH_HAS_SORT_EXTABLE */ #ifndef ARCH_HAS_SEARCH_EXTABLE - -static int cmp_ex_search(const void *key, const void *elt) -{ - const struct exception_table_entry * _elt = elt; - unsigned long k = *(unsigned long*) key; - - /* avoid overflow */ - if (k > ex_to_insn(_elt)) - return 1; - if (k < ex_to_insn(_elt)) - return -1; - return 0; -} - /* * Search one exception table for an entry corresponding to the * given instruction address, and return the address of the entry, @@ -117,9 +102,24 @@ static int cmp_ex_search(const void *key, const void *elt) */ const struct exception_table_entry * search_extable(const struct exception_table_entry *first, - const size_t num, + const struct exception_table_entry *last, unsigned long value) { - return bsearch(&value, first, num, sizeof(struct exception_table_entry), cmp_ex_search); + while (first <= last) { + const struct exception_table_entry *mid; + + mid = ((last - first) >> 1) + first; + /* + * careful, the distance between value and insn + * can be larger than MAX_LONG: + */ + if (ex_to_insn(mid) < value) + first = mid + 1; + else if (ex_to_insn(mid) > value) + last = mid - 1; + else + return mid; + } + return NULL; } #endif |