File: /usr/src/linux/arch/sh/mm/extable.c

1     /* $Id: extable.c,v 1.2 2001/03/31 10:43:18 gniibe Exp $
2      *
3      * linux/arch/sh/mm/extable.c
4      *  Taken from:
5      *   linux/arch/i386/mm/extable.c
6      */
7     
8     #include <linux/config.h>
9     #include <linux/module.h>
10     #include <asm/uaccess.h>
11     
12     extern const struct exception_table_entry __start___ex_table[];
13     extern const struct exception_table_entry __stop___ex_table[];
14     
15     static inline unsigned long
16     search_one_table(const struct exception_table_entry *first,
17     		 const struct exception_table_entry *last,
18     		 unsigned long value)
19     {
20             while (first <= last) {
21     		const struct exception_table_entry *mid;
22     		long diff;
23     
24     		mid = (last - first) / 2 + first;
25     		diff = mid->insn - value;
26                     if (diff == 0)
27                             return mid->fixup;
28                     else if (diff < 0)
29                             first = mid+1;
30                     else
31                             last = mid-1;
32             }
33             return 0;
34     }
35     
36     unsigned long
37     search_exception_table(unsigned long addr)
38     {
39     	unsigned long ret;
40     
41     #ifndef CONFIG_MODULES
42     	/* There is only the kernel to search.  */
43     	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
44     	if (ret) return ret;
45     #else
46     	/* The kernel is the last "module" -- no need to treat it special.  */
47     	struct module *mp;
48     	for (mp = module_list; mp != NULL; mp = mp->next) {
49     		if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
50     			continue;
51     		ret = search_one_table(mp->ex_table_start,
52     				       mp->ex_table_end - 1, addr);
53     		if (ret) return ret;
54     	}
55     #endif
56     
57     	return 0;
58     }
59