void db_restart_at_pc( boolean_t watchpt, task_t task) { db_addr_t pc = PC_REGS(DDB_REGS); #ifdef SOFTWARE_SSTEP db_addr_t brpc; #endif if ((db_run_mode == STEP_COUNT) || (db_run_mode == STEP_RETURN) || (db_run_mode == STEP_CALLT)) { db_expr_t ins; /* * We are about to execute this instruction, * so count it now. */ ins = db_get_task_value(pc, sizeof(int), FALSE, task); db_inst_count++; db_load_count += db_inst_load(ins); db_store_count += db_inst_store(ins); #ifdef SOFTWARE_SSTEP /* Account for instructions in delay slots */ brpc = next_instr_address(pc,1,task); if ((brpc != pc) && (inst_branch(ins) || inst_call(ins))) { /* Note: this ~assumes an instruction <= sizeof(int) */ ins = db_get_task_value(brpc, sizeof(int), FALSE, task); db_inst_count++; db_load_count += db_inst_load(ins); db_store_count += db_inst_store(ins); } #endif /* SOFTWARE_SSTEP */ } if (db_run_mode == STEP_CONTINUE) { if (watchpt || db_find_breakpoint_here(task, pc)) { /* * Step over breakpoint/watchpoint. */ db_run_mode = STEP_INVISIBLE; db_set_task_single_step(DDB_REGS, task); } else { db_set_breakpoints(); db_set_watchpoints(); } } else { db_set_task_single_step(DDB_REGS, task); } }
/* * Set a temporary breakpoint. * The instruction is changed immediately, * so the breakpoint does not have to be on the breakpoint list. */ db_breakpoint_t db_set_temp_breakpoint( task_t task, db_addr_t addr) { register db_breakpoint_t bkpt; bkpt = db_breakpoint_alloc(); if (bkpt == 0) { db_printf("Too many breakpoints.\n"); return 0; } bkpt->task = task; bkpt->address = addr; bkpt->flags = BKPT_TEMP; bkpt->threads = 0; if (db_add_thread_breakpoint(bkpt, 0, 1, FALSE) < 0) { if (bkpt) db_breakpoint_free(bkpt); db_printf("Too many thread_breakpoints.\n"); return 0; } bkpt->bkpt_inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, task); db_put_task_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst), task); return bkpt; }
db_expr_t db_get_value( db_addr_t addr, int size, boolean_t is_signed) { return(db_get_task_value(addr, size, is_signed, TASK_NULL)); }
/* * Write to file. */ void db_write_cmd( db_expr_t address, boolean_t have_addr, db_expr_t count, char * modif) { register db_addr_t addr; register db_expr_t old_value; db_expr_t new_value; register int size; boolean_t wrote_one = FALSE; boolean_t t_opt, u_opt; thread_act_t thr_act; task_t task; addr = (db_addr_t) address; size = db_size_option(modif, &u_opt, &t_opt); if (t_opt) { if (!db_get_next_act(&thr_act, 0)) return; task = thr_act->task; } else task = db_current_space(); /* if user space is not explicitly specified, look in the kernel */ if (!u_opt) task = TASK_NULL; if (!DB_VALID_ADDRESS(addr, u_opt)) { db_printf("Bad address 0x%x\n", addr); return; } while (db_expression(&new_value)) { old_value = db_get_task_value(addr, size, FALSE, task); db_task_printsym(addr, DB_STGY_ANY, task); db_printf("\t\t%#8n\t=\t%#8n\n", old_value, new_value); db_put_task_value(addr, size, new_value, task); addr += size; wrote_one = TRUE; } if (!wrote_one) db_error("Nothing written.\n"); db_next = addr; db_prev = addr - size; }
int db_xcdump( db_addr_t addr, int size, int count, task_t task) { register int i, n; db_expr_t value; int bcount; db_addr_t off; char *name; char data[DB_XCDUMP_NC]; db_find_task_sym_and_offset(addr, &name, &off, task); for (n = count*size; n > 0; n -= bcount) { db_prev = addr; if (off == 0) { db_printf("%s:\n", name); off = -1; } db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr, (size != 1) ? " " : "" ); bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n); if (trunc_page(addr) != trunc_page(addr+bcount-1)) { db_addr_t next_page_addr = trunc_page(addr+bcount-1); if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task)) bcount = next_page_addr - addr; } db_read_bytes((vm_offset_t)addr, bcount, data, task); for (i = 0; i < bcount && off != 0; i += size) { if (i % 4 == 0) db_printf(" "); value = db_get_task_value(addr, size, FALSE, task); db_printf("%0*x ", size*2, value); addr += size; db_find_task_sym_and_offset(addr, &name, &off, task); } db_printf("%*s", ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4, ""); bcount = i; db_printf("%s*", (size != 1)? " ": ""); for (i = 0; i < bcount; i++) { value = data[i]; db_printf("%c", (value >= ' ' && value <= '~')? value: '.'); } db_printf("*\n"); } return(addr); }
int db_numargs( struct i386_frame *fp, task_t task) { long *argp; long inst; long args; extern char etext[]; argp = (long *)db_get_task_value((long)&fp->f_retaddr, sizeof(long), FALSE, task); if (argp < (long *)VM_MIN_KERNEL_ADDRESS || argp > (long *)etext) args = db_numargs_default; else if (!DB_CHECK_ACCESS((long)argp, sizeof(long), task)) args = db_numargs_default; else { inst = db_get_task_value((long)argp, sizeof(long), FALSE, task); if ((inst & 0xff) == 0x59) /* popl %ecx */ args = 1; else if ((inst & 0xffff) == 0xc483) /* addl %n, %esp */ args = ((inst >> 16) & 0xff) / 4; else args = db_numargs_default; }
void db_set_task_single_step( register db_regs_t *regs, task_t task) { db_addr_t pc = PC_REGS(regs), brpc; register unsigned int inst; register boolean_t unconditional; /* * User was stopped at pc, e.g. the instruction * at pc was not executed. */ inst = db_get_task_value(pc, sizeof(int), FALSE, task); if (inst_branch(inst) || inst_call(inst)) { extern db_expr_t getreg_val(); /* XXX -- need prototype! */ brpc = branch_taken(inst, pc, getreg_val, (unsigned char*)regs); if (brpc != pc) { /* self-branches are hopeless */ db_taken_bkpt = db_set_temp_breakpoint(task, brpc); } else db_taken_bkpt = 0; pc = next_instr_address(pc,1,task); } else pc = next_instr_address(pc,0,task); /* * check if this control flow instruction is an * unconditional transfer */ unconditional = inst_unconditional_flow_transfer(inst); /* We only set the sequential breakpoint if previous instruction was not an unconditional change of flow of control. If the previous instruction is an unconditional change of flow of control, setting a breakpoint in the next sequential location may set a breakpoint in data or in another routine, which could screw up either the program or the debugger. (Consider, for instance, that the next sequential instruction is the start of a routine needed by the debugger.) */ if (!unconditional && db_find_breakpoint_here(task, pc) == 0 && (db_taken_bkpt == 0 || db_taken_bkpt->address != pc)) { db_not_taken_bkpt = db_set_temp_breakpoint(task, pc); } else db_not_taken_bkpt = 0; }
void db_search( db_addr_t addr, int size, db_expr_t value, db_expr_t mask, unsigned int count, task_t task) { while (count-- != 0) { db_prev = addr; if ((db_get_task_value(addr,size,FALSE,task) & mask) == value) break; addr += size; } db_printf("0x%x: ", addr); db_next = addr; }
void db_clear_breakpoints(void) { register db_breakpoint_t bkpt, *bkptp; register task_t task; db_expr_t inst; thread_act_t cur_act = current_act(); task_t cur_task = (cur_act && !cur_act->kernel_loaded) ? cur_act->task: TASK_NULL; if (db_breakpoints_inserted) { bkptp = &db_breakpoint_list; for (bkpt = *bkptp; bkpt; bkpt = *bkptp) { task = bkpt->task; if (bkpt->flags & BKPT_USR_GLOBAL) { if (cur_task == TASK_NULL) { bkptp = &bkpt->link; continue; } task = cur_task; } if ((bkpt->flags & BKPT_SET_IN_MEM) && DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) { inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, task); if (inst != BKPT_SET(inst)) { if (bkpt->flags & BKPT_USR_GLOBAL) { bkptp = &bkpt->link; continue; } db_force_delete_breakpoint(bkpt, 0, FALSE); *bkptp = bkpt->link; db_breakpoint_free(bkpt); continue; } db_put_task_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst, task); bkpt->flags &= ~BKPT_SET_IN_MEM; } bkptp = &bkpt->link; } db_breakpoints_inserted = FALSE; } }
void db_set_breakpoints(void) { register db_breakpoint_t bkpt; register task_t task; db_expr_t inst; thread_act_t cur_act = current_act(); task_t cur_task = (cur_act && !cur_act->kernel_loaded) ? cur_act->task : TASK_NULL; boolean_t inserted = TRUE; if (!db_breakpoints_inserted) { for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { if (bkpt->flags & BKPT_SET_IN_MEM) continue; task = bkpt->task; if (bkpt->flags & BKPT_USR_GLOBAL) { if ((bkpt->flags & BKPT_1ST_SET) == 0) { if (cur_task == TASK_NULL) continue; task = cur_task; } else bkpt->flags &= ~BKPT_1ST_SET; } if (DB_CHECK_ACCESS(bkpt->address, BKPT_SIZE, task)) { inst = db_get_task_value(bkpt->address, BKPT_SIZE, FALSE, task); if (inst == BKPT_SET(inst)) continue; bkpt->bkpt_inst = inst; db_put_task_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst), task); bkpt->flags |= BKPT_SET_IN_MEM; } else { inserted = FALSE; } } db_breakpoints_inserted = inserted; } }
/* * Disassemble instruction at 'loc'. 'altfmt' specifies an * (optional) alternate format. Return address of start of * next instruction. */ db_addr_t db_disasm( db_addr_t loc, boolean_t altfmt, task_t task) { int inst; char *p; inst = db_get_task_value(loc, 4, FALSE, task); db_disasm_pc = loc; db_disasm_print_symaddr = FALSE; p = in(inst); db_printf("%s", p); if (db_disasm_print_symaddr) { db_printf(" <"); db_task_printsym(db_disasm_symaddr, DB_STGY_ANY, task); db_printf(">"); } dis_done(); return (loc+4); }
/* * Disassemble instruction at 'loc'. 'altfmt' specifies an * (optional) alternate format. Return address of start of * next instruction. */ db_addr_t db_disasm( db_addr_t loc, boolean_t altfmt, task_t task) { int inst; char *p; inst = db_get_task_value(loc, 4, FALSE, task); db_disasm_pc = loc; db_disasm_print_symaddr = FALSE; p = in(inst); db_printf("%s", p); if (db_disasm_print_symaddr) { db_printf(" <"); db_task_printsym(db_disasm_symaddr, DB_STGY_ANY, task); db_printf(">"); } db_printf("\n"); /* Make sure we have a new line for multiline displays */ dis_done(); return (loc+4); }
boolean_t kdb_trap( int type, int code, struct i386_saved_state *regs) { spl_t s; s = splhigh(); saved_ipl[cpu_number()] = s; switch (type) { case T_DEBUG: /* single_step */ { int addr; int status = get_dr6(); if (status & 0xf) { /* hmm hdw break */ addr = status & 0x8 ? get_dr3() : status & 0x4 ? get_dr2() : status & 0x2 ? get_dr1() : get_dr0(); regs->efl |= EFL_RF; db_single_step_cmd(addr, 0, 1, "p"); } } case T_INT3: /* breakpoint */ case T_WATCHPOINT: /* watchpoint */ case -1: /* keyboard interrupt */ break; default: if (db_recover) { i386_nested_saved_state = *regs; db_printf("Caught %s (%d), code = %x, pc = %x\n", trap_name(type), type, code, regs->eip); db_error(""); /*NOTREACHED*/ } kdbprinttrap(type, code); } #if NCPUS > 1 if (db_enter()) #endif /* NCPUS > 1 */ { i386_last_saved_statep = regs; i386_last_kdb_sp = (unsigned) &type; /* XXX Should switch to ddb`s own stack here. */ ddb_regs = *regs; if ((regs->cs & 0x3) == KERNEL_RING) { /* * Kernel mode - esp and ss not saved */ ddb_regs.uesp = (int)®s->uesp; /* kernel stack pointer */ ddb_regs.ss = KERNEL_DS; } cnpollc(TRUE); db_task_trap(type, code, (regs->cs & 0x3) != 0); cnpollc(FALSE); regs->eip = ddb_regs.eip; regs->efl = ddb_regs.efl; regs->eax = ddb_regs.eax; regs->ecx = ddb_regs.ecx; regs->edx = ddb_regs.edx; regs->ebx = ddb_regs.ebx; if ((regs->cs & 0x3) != KERNEL_RING) { /* * user mode - saved esp and ss valid */ regs->uesp = ddb_regs.uesp; /* user stack pointer */ regs->ss = ddb_regs.ss & 0xffff; /* user stack segment */ } regs->ebp = ddb_regs.ebp; regs->esi = ddb_regs.esi; regs->edi = ddb_regs.edi; regs->es = ddb_regs.es & 0xffff; regs->cs = ddb_regs.cs & 0xffff; regs->ds = ddb_regs.ds & 0xffff; regs->fs = ddb_regs.fs & 0xffff; regs->gs = ddb_regs.gs & 0xffff; if ((type == T_INT3) && (db_get_task_value(regs->eip, BKPT_SIZE, FALSE, TASK_NULL) == BKPT_INST)) regs->eip += BKPT_SIZE; } #if NCPUS > 1 db_leave(); #endif /* NCPUS > 1 */ splx(s); return 1; }
boolean_t db_stop_at_pc( boolean_t *is_breakpoint, task_t task, task_t space) { register db_thread_breakpoint_t bkpt; db_clear_task_single_step(DDB_REGS, space); db_clear_breakpoints(); db_clear_watchpoints(); db_stop_pc = PC_REGS(DDB_REGS); #ifdef FIXUP_PC_AFTER_BREAK if (*is_breakpoint) { /* * Breakpoint trap. Fix up the PC if the * machine requires it. */ FIXUP_PC_AFTER_BREAK db_stop_pc = PC_REGS(DDB_REGS); } #endif /* * Now check for a breakpoint at this address. */ bkpt = db_find_thread_breakpoint_here(space, db_stop_pc); if (bkpt) { if (db_cond_check(bkpt)) { *is_breakpoint = TRUE; return (TRUE); /* stop here */ } } *is_breakpoint = FALSE; if (db_run_mode == STEP_INVISIBLE) { db_run_mode = STEP_CONTINUE; return (FALSE); /* continue */ } if (db_run_mode == STEP_COUNT) { return (FALSE); /* continue */ } if (db_run_mode == STEP_ONCE) { if (--db_loop_count > 0) { if (db_sstep_print) { db_print_loc_and_inst(db_stop_pc, task); } return (FALSE); /* continue */ } } if (db_run_mode == STEP_RETURN) { jmp_buf_t *prev; jmp_buf_t db_jmpbuf; /* WARNING: the following assumes an instruction fits an int */ db_expr_t ins; ins = db_get_task_value(db_stop_pc, sizeof(int), FALSE, space); /* continue until matching return */ prev = db_recover; if (_setjmp(db_recover = &db_jmpbuf) == 0) { if (!inst_trap_return(ins) && (!inst_return(ins) || --db_call_depth != 0)) { if (db_sstep_print) { if (inst_call(ins) || inst_return(ins)) { register int i; db_printf("[after %6d /%4d] ", db_inst_count, db_inst_count - db_last_inst_count); db_last_inst_count = db_inst_count; for (i = db_call_depth; --i > 0; ) db_printf(" "); db_print_loc_and_inst(db_stop_pc, task); db_printf("\n"); } } if (inst_call(ins)) db_call_depth++; db_recover = prev; if (db_step_again()) return (FALSE); /* continue */ } } db_recover = prev; } if (db_run_mode == STEP_CALLT) { /* WARNING: the following assumes an instruction fits an int */ db_expr_t ins; ins = db_get_task_value(db_stop_pc, sizeof(int), FALSE, space); /* continue until call or return */ if (!inst_call(ins) && !inst_return(ins) && !inst_trap_return(ins)) { if (db_step_again()) return (FALSE); /* continue */ } } if (db_find_breakpoint_here(space, db_stop_pc)) return(FALSE); db_run_mode = STEP_NONE; return (TRUE); }
void db_examine( db_addr_t addr, char * fmt, /* format string */ int count, /* repeat count */ task_t task) { int c; db_expr_t value; int size; int width; int leader; int items; int nitems; char * fp; db_addr_t next_addr; int sz; db_examine_prev_addr = addr; while (--count >= 0) { fp = fmt; size = sizeof(int); width = db_examine_width(size, &items, &leader); while ((c = *fp++) != 0) { switch (c) { case 'b': size = sizeof(char); width = db_examine_width(size, &items, &leader); break; case 'h': size = sizeof(short); width = db_examine_width(size, &items, &leader); break; case 'l': size = sizeof(int); width = db_examine_width(size, &items, &leader); break; case 'q': size = sizeof(long); width = db_examine_width(size, &items, &leader); break; case 'a': /* address */ case 'A': /* function address */ /* always forces a new line */ if (db_print_position() != 0) db_printf("\n"); db_prev = addr; next_addr = addr + 4; db_task_printsym(addr, (c == 'a')?DB_STGY_ANY:DB_STGY_PROC, task); db_printf(":\t"); break; case 'm': db_next = db_xcdump(addr, size, count+1, task); return; case 't': case 'u': break; default: restart: /* Reset next_addr in case we are printing in multiple formats. */ next_addr = addr; if (db_print_position() == 0) { /* If we hit a new symbol, print it */ char * name; db_addr_t off; db_find_task_sym_and_offset(addr,&name,&off,task); if (off == 0) db_printf("\r%s:\n", name); db_printf("%#n: ", addr); for (sz = 0; sz < leader; sz++) db_putchar(' '); db_prev = addr; nitems = items; } switch (c) { case 'p': /* Addrs rendered symbolically. */ if( size == sizeof(void *) ) { char *symName; db_addr_t offset; items = 1; value = db_get_task_value( next_addr, sizeof(db_expr_t), FALSE, task ); db_find_task_sym_and_offset( value, &symName, &offset, task); db_printf("\n\t*%8x(%8X) = %s", next_addr, value, symName ); if( offset ) { db_printf("+%X", offset ); } next_addr += size; } break; case 'r': /* signed, current radix */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), TRUE,task); db_printf("%-*r", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, TRUE, task); db_printf("%-*R", width, value); next_addr += sz; } break; case 'x': /* unsigned hex */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), FALSE,task); db_printf("%-*x", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, FALSE, task); db_printf("%-*X", width, value); next_addr += sz; } break; case 'z': /* signed hex */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), TRUE, task); db_printf("%-*z", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr,sz, TRUE,task); db_printf("%-*Z", width, value); next_addr += sz; } break; case 'd': /* signed decimal */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), TRUE,task); db_printf("%-*d", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, TRUE, task); db_printf("%-*D", width, value); next_addr += sz; } break; case 'U': /* unsigned decimal */ case 'u': for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), FALSE,task); db_printf("%-*u", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, FALSE, task); db_printf("%-*U", width, value); next_addr += sz; } break; case 'o': /* unsigned octal */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), FALSE,task); db_printf("%-*o", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, FALSE, task); db_printf("%-*o", width, value); next_addr += sz; } break; case 'c': /* character */ for (sz = 0, next_addr = addr; sz < size; sz++, next_addr++) { value = db_get_task_value(next_addr,1, FALSE,task); if ((value >= ' ' && value <= '~') || value == '\n' || value == '\t') db_printf("%c", value); else db_printf("\\%03o", value); } break; case 's': /* null-terminated string */ size = 0; for (;;) { value = db_get_task_value(next_addr,1, FALSE,task); next_addr += 1; size++; if (value == 0) break; if (value >= ' ' && value <= '~') db_printf("%c", value); else db_printf("\\%03o", value); } break; case 'i': /* instruction */ next_addr = db_disasm(addr, FALSE, task); size = next_addr - addr; break; case 'I': /* instruction, alternate form */ next_addr = db_disasm(addr, TRUE, task); size = next_addr - addr; break; default: break; } if (db_print_position() != 0) db_end_line(); break; } } addr = next_addr; } db_next = addr; }
/* * kdb_trap - field a TRACE or BPT trap */ void kdb_trap( int type, struct savearea *regs) { boolean_t trap_from_user; int previous_console_device; int code=0; previous_console_device=switch_to_serial_console(); switch (type) { case T_TRACE: /* single_step */ case T_PROGRAM: /* breakpoint */ #if 0 case T_WATCHPOINT: /* watchpoint */ #endif case -1: /* keyboard interrupt */ break; default: if (db_recover) { ppc_nested_saved_state = *regs; db_printf("Caught "); if (type > TRAP_TYPES) db_printf("type %d", type); else db_printf("%s", trap_type[type]); db_printf(" trap, pc = %x\n", regs->save_srr0); db_error(""); /*NOTREACHED*/ } kdbprinttrap(type, code, (int *)®s->save_srr0, regs->save_r1); } saved_state[cpu_number()] = regs; ppc_last_saved_statep = regs; ppc_last_kdb_sp = (unsigned) &type; if (!IS_USER_TRAP(regs)) { bzero((char *)&ddb_regs, sizeof (ddb_regs)); ddb_regs = *regs; trap_from_user = FALSE; } else { ddb_regs = *regs; trap_from_user = TRUE; } db_task_trap(type, code, trap_from_user); *regs = ddb_regs; if ((type == T_PROGRAM) && (db_get_task_value(regs->save_srr0, BKPT_SIZE, FALSE, db_target_space(current_act(), trap_from_user)) == BKPT_INST)) regs->save_srr0 += BKPT_SIZE; kdb_exit: saved_state[cpu_number()] = 0; switch_to_old_console(previous_console_device); }