void kdp_trap( unsigned int exception, struct savearea *saved_state ) { unsigned int *fp; unsigned int sp; if (kdp_noisy) { if (kdp_backtrace) { printf("\nvector=%x, \n", exception/4); sp = saved_state->save_r1; printf("stack backtrace - sp(%x) ", sp); fp = (unsigned int *) *((unsigned int *)sp); while (fp) { printf("0x%08x ", fp[2]); fp = (unsigned int *)*fp; } printf("\n"); } #ifdef XXX if (kdp_sr_dump) { dump_segment_registers(); } #endif printf("vector=%d ", exception/4); } kdp_raise_exception(kdp_code(exception), 0, 0, saved_state); if (kdp_noisy) printf("kdp_trap: kdp_raise_exception() ret\n"); if ((unsigned int)(saved_state->save_srr0) == 0x7c800008) saved_state->save_srr0 += 4; /* BKPT_SIZE */ if(saved_state->save_srr1 & (MASK(MSR_SE) | MASK(MSR_BE))) { /* Are we just stepping or continuing */ db_run_mode = STEP_ONCE; /* We are stepping */ } else db_run_mode = STEP_CONTINUE; /* Otherwise we are continuing */ #ifdef XXX mtspr(dabr, kdp_dabr); #endif }
/* Intended to be called from the kernel trap handler if an unrecoverable fault * occurs during a crashdump (which shouldn't happen since we validate mappings * and so on). This should be reworked to attempt some form of recovery. */ int kdp_dump_trap( int type, __unused x86_saved_state64_t *saved_state) { printf ("An unexpected trap (type %d) occurred during the system dump, terminating.\n", type); kdp_send_crashdump_pkt (KDP_EOF, NULL, 0, ((void *) 0)); abort_panic_transfer(); kdp_flag &= ~KDP_PANIC_DUMP_ENABLED; kdp_flag &= ~PANIC_CORE_ON_NMI; kdp_flag &= ~PANIC_LOG_DUMP; kdp_reset(); kdp_raise_exception(EXC_BAD_ACCESS, 0, 0, kdp.saved_state); return( 0 ); }
boolean_t kdp_i386_trap( unsigned int trapno, x86_saved_state64_t *saved_state, kern_return_t result, vm_offset_t va ) { unsigned int exception, subcode = 0, code; if (trapno != T_INT3 && trapno != T_DEBUG) { kprintf("Debugger: Unexpected kernel trap number: " "0x%x, RIP: 0x%llx, CR2: 0x%llx\n", trapno, saved_state->isf.rip, saved_state->cr2); if (!kdp.is_conn) return FALSE; } mp_kdp_enter(); kdp_callouts(KDP_EVENT_ENTER); if (saved_state->isf.rflags & EFL_TF) { enable_preemption_no_check(); } switch (trapno) { case T_DIVIDE_ERROR: exception = EXC_ARITHMETIC; code = EXC_I386_DIVERR; break; case T_OVERFLOW: exception = EXC_SOFTWARE; code = EXC_I386_INTOFLT; break; case T_OUT_OF_BOUNDS: exception = EXC_ARITHMETIC; code = EXC_I386_BOUNDFLT; break; case T_INVALID_OPCODE: exception = EXC_BAD_INSTRUCTION; code = EXC_I386_INVOPFLT; break; case T_SEGMENT_NOT_PRESENT: exception = EXC_BAD_INSTRUCTION; code = EXC_I386_SEGNPFLT; subcode = (unsigned int)saved_state->isf.err; break; case T_STACK_FAULT: exception = EXC_BAD_INSTRUCTION; code = EXC_I386_STKFLT; subcode = (unsigned int)saved_state->isf.err; break; case T_GENERAL_PROTECTION: exception = EXC_BAD_INSTRUCTION; code = EXC_I386_GPFLT; subcode = (unsigned int)saved_state->isf.err; break; case T_PAGE_FAULT: exception = EXC_BAD_ACCESS; code = result; subcode = (unsigned int)va; break; case T_WATCHPOINT: exception = EXC_SOFTWARE; code = EXC_I386_ALIGNFLT; break; case T_DEBUG: case T_INT3: exception = EXC_BREAKPOINT; code = EXC_I386_BPTFLT; break; default: exception = EXC_BAD_INSTRUCTION; code = trapno; break; } if (current_cpu_datap()->cpu_fatal_trap_state) { current_cpu_datap()->cpu_post_fatal_trap_state = saved_state; saved_state = current_cpu_datap()->cpu_fatal_trap_state; } kdp_raise_exception(exception, code, subcode, saved_state); /* If the instruction single step bit is set, disable kernel preemption */ if (saved_state->isf.rflags & EFL_TF) { disable_preemption(); } kdp_callouts(KDP_EVENT_EXIT); mp_kdp_exit(); return TRUE; }