extable.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:2k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.extable.c 1.5 05/17/01 18:14:23 cort
  3.  */
  4. /*
  5.  * linux/arch/ppc/mm/extable.c
  6.  *
  7.  * from linux/arch/i386/mm/extable.c
  8.  */
  9. #include <linux/config.h>
  10. #include <linux/module.h>
  11. #include <asm/uaccess.h>
  12. extern struct exception_table_entry __start___ex_table[];
  13. extern struct exception_table_entry __stop___ex_table[];
  14. /*
  15.  * The exception table needs to be sorted because we use the macros
  16.  * which put things into the exception table in a variety of segments
  17.  * such as the prep, pmac, chrp, etc. segments as well as the init
  18.  * segment and the main kernel text segment.
  19.  */
  20. static inline void
  21. sort_ex_table(struct exception_table_entry *start,
  22.       struct exception_table_entry *finish)
  23. {
  24. struct exception_table_entry el, *p, *q;
  25. /* insertion sort */
  26. for (p = start + 1; p < finish; ++p) {
  27. /* start .. p-1 is sorted */
  28. if (p[0].insn < p[-1].insn) {
  29. /* move element p down to its right place */
  30. el = *p;
  31. q = p;
  32. do {
  33. /* el comes before q[-1], move q[-1] up one */
  34. q[0] = q[-1];
  35. --q;
  36. } while (q > start && el.insn < q[-1].insn);
  37. *q = el;
  38. }
  39. }
  40. }
  41. void
  42. sort_exception_table(void)
  43. {
  44. sort_ex_table(__start___ex_table, __stop___ex_table);
  45. }
  46. static inline unsigned long
  47. search_one_table(const struct exception_table_entry *first,
  48.  const struct exception_table_entry *last,
  49.  unsigned long value)
  50. {
  51.         while (first <= last) {
  52. const struct exception_table_entry *mid;
  53. long diff;
  54. mid = (last - first) / 2 + first;
  55. diff = mid->insn - value;
  56.                 if (diff == 0)
  57.                         return mid->fixup;
  58.                 else if (diff < 0)
  59.                         first = mid+1;
  60.                 else
  61.                         last = mid-1;
  62.         }
  63.         return 0;
  64. }
  65. unsigned long
  66. search_exception_table(unsigned long addr)
  67. {
  68. unsigned long ret;
  69. #ifndef CONFIG_MODULES
  70. /* There is only the kernel to search.  */
  71. ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
  72. if (ret) return ret;
  73. #else
  74. /* The kernel is the last "module" -- no need to treat it special.  */
  75. struct module *mp;
  76. for (mp = module_list; mp != NULL; mp = mp->next) {
  77. if (mp->ex_table_start == NULL)
  78. continue;
  79. ret = search_one_table(mp->ex_table_start,
  80.        mp->ex_table_end - 1, addr);
  81. if (ret)
  82. return ret;
  83. }
  84. #endif
  85. return 0;
  86. }