Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thomas Meyer and committed by
Linus Torvalds
a94c33dd 12e8fd6f

+63 -56
+2 -1
arch/mips/kernel/module.c
··· 317 317 318 318 spin_lock_irqsave(&dbe_lock, flags); 319 319 list_for_each_entry(dbe, &dbe_list, dbe_list) { 320 - e = search_extable(dbe->dbe_start, dbe->dbe_end - 1, addr); 320 + e = search_extable(dbe->dbe_start, 321 + dbe->dbe_end - dbe->dbe_start, addr); 321 322 if (e) 322 323 break; 323 324 }
+2 -1
arch/mips/kernel/traps.c
··· 429 429 { 430 430 const struct exception_table_entry *e; 431 431 432 - e = search_extable(__start___dbe_table, __stop___dbe_table - 1, addr); 432 + e = search_extable(__start___dbe_table, 433 + __stop___dbe_table - __start___dbe_table, addr); 433 434 if (!e) 434 435 e = search_module_dbetables(addr); 435 436 return e;
+18 -16
arch/sh/mm/extable_64.c
··· 10 10 * License. See the file "COPYING" in the main directory of this archive 11 11 * for more details. 12 12 */ 13 + #include <linux/bsearch.h> 13 14 #include <linux/rwsem.h> 14 15 #include <linux/extable.h> 15 16 #include <linux/uaccess.h> ··· 41 40 return NULL; 42 41 } 43 42 43 + static int cmp_ex_search(const void *key, const void *elt) 44 + { 45 + const struct exception_table_entry *_elt = elt; 46 + unsigned long _key = *(unsigned long *)key; 47 + 48 + /* avoid overflow */ 49 + if (_key > _elt->insn) 50 + return 1; 51 + if (_key < _elt->insn) 52 + return -1; 53 + return 0; 54 + } 55 + 44 56 /* Simple binary search */ 45 57 const struct exception_table_entry * 46 - search_extable(const struct exception_table_entry *first, 47 - const struct exception_table_entry *last, 58 + search_extable(const struct exception_table_entry *base, 59 + const size_t num, 48 60 unsigned long value) 49 61 { 50 62 const struct exception_table_entry *mid; ··· 66 52 if (mid) 67 53 return mid; 68 54 69 - while (first <= last) { 70 - long diff; 71 - 72 - mid = (last - first) / 2 + first; 73 - diff = mid->insn - value; 74 - if (diff == 0) 75 - return mid; 76 - else if (diff < 0) 77 - first = mid+1; 78 - else 79 - last = mid-1; 80 - } 81 - 82 - return NULL; 55 + return bsearch(&value, base, num, 56 + sizeof(struct exception_table_entry), cmp_ex_search); 83 57 } 84 58 85 59 int fixup_exception(struct pt_regs *regs)
+14 -14
arch/sparc/mm/extable.c
··· 13 13 14 14 /* Caller knows they are in a range if ret->fixup == 0 */ 15 15 const struct exception_table_entry * 16 - search_extable(const struct exception_table_entry *start, 17 - const struct exception_table_entry *last, 16 + search_extable(const struct exception_table_entry *base, 17 + const size_t num, 18 18 unsigned long value) 19 19 { 20 - const struct exception_table_entry *walk; 20 + int i; 21 21 22 22 /* Single insn entries are encoded as: 23 23 * word 1: insn address ··· 37 37 */ 38 38 39 39 /* 1. Try to find an exact match. */ 40 - for (walk = start; walk <= last; walk++) { 41 - if (walk->fixup == 0) { 40 + for (i = 0; i < num; i++) { 41 + if (base[i].fixup == 0) { 42 42 /* A range entry, skip both parts. */ 43 - walk++; 43 + i++; 44 44 continue; 45 45 } 46 46 47 47 /* A deleted entry; see trim_init_extable */ 48 - if (walk->fixup == -1) 48 + if (base[i].fixup == -1) 49 49 continue; 50 50 51 - if (walk->insn == value) 52 - return walk; 51 + if (base[i].insn == value) 52 + return &base[i]; 53 53 } 54 54 55 55 /* 2. Try to find a range match. */ 56 - for (walk = start; walk <= (last - 1); walk++) { 57 - if (walk->fixup) 56 + for (i = 0; i < (num - 1); i++) { 57 + if (base[i].fixup) 58 58 continue; 59 59 60 - if (walk[0].insn <= value && walk[1].insn > value) 61 - return walk; 60 + if (base[i].insn <= value && base[i + 1].insn > value) 61 + return &base[i]; 62 62 63 - walk++; 63 + i++; 64 64 } 65 65 66 66 return NULL;
+3 -2
include/linux/extable.h
··· 2 2 #define _LINUX_EXTABLE_H 3 3 4 4 #include <linux/stddef.h> /* for NULL */ 5 + #include <linux/types.h> 5 6 6 7 struct module; 7 8 struct exception_table_entry; 8 9 9 10 const struct exception_table_entry * 10 - search_extable(const struct exception_table_entry *first, 11 - const struct exception_table_entry *last, 11 + search_extable(const struct exception_table_entry *base, 12 + const size_t num, 12 13 unsigned long value); 13 14 void sort_extable(struct exception_table_entry *start, 14 15 struct exception_table_entry *finish);
+2 -1
kernel/extable.c
··· 55 55 { 56 56 const struct exception_table_entry *e; 57 57 58 - e = search_extable(__start___ex_table, __stop___ex_table-1, addr); 58 + e = search_extable(__start___ex_table, 59 + __stop___ex_table - __start___ex_table, addr); 59 60 if (!e) 60 61 e = search_module_extables(addr); 61 62 return e;
+1 -1
kernel/module.c
··· 4196 4196 goto out; 4197 4197 4198 4198 e = search_extable(mod->extable, 4199 - mod->extable + mod->num_exentries - 1, 4199 + mod->num_exentries, 4200 4200 addr); 4201 4201 out: 4202 4202 preempt_enable();
+21 -20
lib/extable.c
··· 9 9 * 2 of the License, or (at your option) any later version. 10 10 */ 11 11 12 + #include <linux/bsearch.h> 12 13 #include <linux/module.h> 13 14 #include <linux/init.h> 14 15 #include <linux/sort.h> ··· 52 51 * This is used both for the kernel exception table and for 53 52 * the exception tables of modules that get loaded. 54 53 */ 55 - static int cmp_ex(const void *a, const void *b) 54 + static int cmp_ex_sort(const void *a, const void *b) 56 55 { 57 56 const struct exception_table_entry *x = a, *y = b; 58 57 ··· 68 67 struct exception_table_entry *finish) 69 68 { 70 69 sort(start, finish - start, sizeof(struct exception_table_entry), 71 - cmp_ex, swap_ex); 70 + cmp_ex_sort, swap_ex); 72 71 } 73 72 74 73 #ifdef CONFIG_MODULES ··· 94 93 #endif /* !ARCH_HAS_SORT_EXTABLE */ 95 94 96 95 #ifndef ARCH_HAS_SEARCH_EXTABLE 96 + 97 + static int cmp_ex_search(const void *key, const void *elt) 98 + { 99 + const struct exception_table_entry *_elt = elt; 100 + unsigned long _key = *(unsigned long *)key; 101 + 102 + /* avoid overflow */ 103 + if (_key > ex_to_insn(_elt)) 104 + return 1; 105 + if (_key < ex_to_insn(_elt)) 106 + return -1; 107 + return 0; 108 + } 109 + 97 110 /* 98 111 * Search one exception table for an entry corresponding to the 99 112 * given instruction address, and return the address of the entry, ··· 116 101 * already sorted. 117 102 */ 118 103 const struct exception_table_entry * 119 - search_extable(const struct exception_table_entry *first, 120 - const struct exception_table_entry *last, 104 + search_extable(const struct exception_table_entry *base, 105 + const size_t num, 121 106 unsigned long value) 122 107 { 123 - while (first <= last) { 124 - const struct exception_table_entry *mid; 125 - 126 - mid = ((last - first) >> 1) + first; 127 - /* 128 - * careful, the distance between value and insn 129 - * can be larger than MAX_LONG: 130 - */ 131 - if (ex_to_insn(mid) < value) 132 - first = mid + 1; 133 - else if (ex_to_insn(mid) > value) 134 - last = mid - 1; 135 - else 136 - return mid; 137 - } 138 - return NULL; 108 + return bsearch(&value, base, num, 109 + sizeof(struct exception_table_entry), cmp_ex_search); 139 110 } 140 111 #endif