const struct exception_table_entry * search_extable (const struct exception_table_entry *first, const struct exception_table_entry *last, unsigned long ip) { const struct exception_table_entry *mid; unsigned long mid_ip; long diff; while (first <= last) { mid = &first[(last - first)/2]; mid_ip = (u64) &mid->addr + mid->addr; diff = mid_ip - ip; if (diff == 0) return mid; else if (diff < 0) first = mid + 1; else last = mid - 1; } #ifdef CONFIG_KGDB if (atomic_read(&debugger_active) && kgdb_may_fault) kgdb_fault_longjmp(kgdb_fault_jmp_regs); /* Not reached. */ #endif return NULL; }
int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fixup; fixup = search_exception_tables(regs->pc); if (fixup) { regs->pc = fixup->fixup; return 1; } #ifdef CONFIG_KGDB if (atomic_read(&debugger_active) && kgdb_may_fault) /* Restore our previous state. */ kgdb_fault_longjmp(kgdb_fault_jmp_regs); /* Never reached. */ #endif return 0; }