diff options
author | Thomas Meyer <thomas@m3y3r.de> | 2017-07-10 18:51:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-10 19:32:35 -0400 |
commit | a94c33dd1f677d16c4f1a162b4b3e9eba1b07c24 (patch) | |
tree | c5a55e93fc355f73d614b0608dac3652b8048adf /lib/extable.c | |
parent | 12e8fd6fd380261fd200d2e8f7a519ade73ea05b (diff) |
lib/extable.c: use bsearch() library function in search_extable()
[thomas@m3y3r.de: v3: fix arch specific implementations]
Link: http://lkml.kernel.org/r/1497890858.12931.7.camel@m3y3r.de
Signed-off-by: Thomas Meyer <thomas@m3y3r.de>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/extable.c')
-rw-r--r-- | lib/extable.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/lib/extable.c b/lib/extable.c index 62968daa66a9..f54996fdd0b8 100644 --- a/lib/extable.c +++ b/lib/extable.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/bsearch.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
14 | #include <linux/sort.h> | 15 | #include <linux/sort.h> |
@@ -51,7 +52,7 @@ static void swap_ex(void *a, void *b, int size) | |||
51 | * This is used both for the kernel exception table and for | 52 | * This is used both for the kernel exception table and for |
52 | * the exception tables of modules that get loaded. | 53 | * the exception tables of modules that get loaded. |
53 | */ | 54 | */ |
54 | static int cmp_ex(const void *a, const void *b) | 55 | static int cmp_ex_sort(const void *a, const void *b) |
55 | { | 56 | { |
56 | const struct exception_table_entry *x = a, *y = b; | 57 | const struct exception_table_entry *x = a, *y = b; |
57 | 58 | ||
@@ -67,7 +68,7 @@ void sort_extable(struct exception_table_entry *start, | |||
67 | struct exception_table_entry *finish) | 68 | struct exception_table_entry *finish) |
68 | { | 69 | { |
69 | sort(start, finish - start, sizeof(struct exception_table_entry), | 70 | sort(start, finish - start, sizeof(struct exception_table_entry), |
70 | cmp_ex, swap_ex); | 71 | cmp_ex_sort, swap_ex); |
71 | } | 72 | } |
72 | 73 | ||
73 | #ifdef CONFIG_MODULES | 74 | #ifdef CONFIG_MODULES |
@@ -93,6 +94,20 @@ void trim_init_extable(struct module *m) | |||
93 | #endif /* !ARCH_HAS_SORT_EXTABLE */ | 94 | #endif /* !ARCH_HAS_SORT_EXTABLE */ |
94 | 95 | ||
95 | #ifndef ARCH_HAS_SEARCH_EXTABLE | 96 | #ifndef ARCH_HAS_SEARCH_EXTABLE |
97 | |||
98 | static int cmp_ex_search(const void *key, const void *elt) | ||
99 | { | ||
100 | const struct exception_table_entry *_elt = elt; | ||
101 | unsigned long _key = *(unsigned long *)key; | ||
102 | |||
103 | /* avoid overflow */ | ||
104 | if (_key > ex_to_insn(_elt)) | ||
105 | return 1; | ||
106 | if (_key < ex_to_insn(_elt)) | ||
107 | return -1; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
96 | /* | 111 | /* |
97 | * Search one exception table for an entry corresponding to the | 112 | * Search one exception table for an entry corresponding to the |
98 | * given instruction address, and return the address of the entry, | 113 | * given instruction address, and return the address of the entry, |
@@ -101,25 +116,11 @@ void trim_init_extable(struct module *m) | |||
101 | * already sorted. | 116 | * already sorted. |
102 | */ | 117 | */ |
103 | const struct exception_table_entry * | 118 | const struct exception_table_entry * |
104 | search_extable(const struct exception_table_entry *first, | 119 | search_extable(const struct exception_table_entry *base, |
105 | const struct exception_table_entry *last, | 120 | const size_t num, |
106 | unsigned long value) | 121 | unsigned long value) |
107 | { | 122 | { |
108 | while (first <= last) { | 123 | return bsearch(&value, base, num, |
109 | const struct exception_table_entry *mid; | 124 | sizeof(struct exception_table_entry), cmp_ex_search); |
110 | |||
111 | mid = ((last - first) >> 1) + first; | ||
112 | /* | ||
113 | * careful, the distance between value and insn | ||
114 | * can be larger than MAX_LONG: | ||
115 | */ | ||
116 | if (ex_to_insn(mid) < value) | ||
117 | first = mid + 1; | ||
118 | else if (ex_to_insn(mid) > value) | ||
119 | last = mid - 1; | ||
120 | else | ||
121 | return mid; | ||
122 | } | ||
123 | return NULL; | ||
124 | } | 125 | } |
125 | #endif | 126 | #endif |