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); } }
void db_set_single_step(db_regs_t *regs) { db_addr_t pc = PC_REGS(regs), brpc = pc; bool unconditional; unsigned int inst; /* * User was stopped at pc, e.g. the instruction * at pc was not executed. */ inst = db_get_value(pc, sizeof(int), false); if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) { brpc = branch_taken(inst, pc, regs); if (brpc != pc) { /* self-branches are hopeless */ db_set_temp_breakpoint(&db_taken_bkpt, brpc); } else db_taken_bkpt.address = 0; pc = next_instr_address(pc, true); } /* * Check if this control flow instruction is an * unconditional transfer. */ unconditional = inst_unconditional_flow_transfer(inst); pc = next_instr_address(pc, false); /* * We only set the sequential breakpoint if previous * instruction was not an unconditional change of flow * control. If the previous instruction is an * unconditional change of flow control, setting a * breakpoint in the next sequential location may set * a breakpoint in data or in another routine, which * could screw up in either the program or the debugger. * (Consider, for instance, that the next sequential * instruction is the start of a routine needed by the * debugger.) * * Also, don't set both the taken and not-taken breakpoints * in the same place even if the MD code would otherwise * have us do so. */ if (unconditional == false && db_find_breakpoint_here(pc) == 0 && pc != brpc) db_set_temp_breakpoint(&db_not_taken_bkpt, pc); else db_not_taken_bkpt.address = 0; }
void db_restart_at_pc(db_regs_t *regs, bool watchpt) { db_addr_t pc = PC_REGS(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 __unused; /* * We are about to execute this instruction, * so count it now. */ ins = db_get_value(pc, sizeof(int), false); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); #ifdef SOFTWARE_SSTEP /* * Account for instructions in delay slots. */ brpc = next_instr_address(pc, true); if ((brpc != pc) && (inst_branch(ins) || inst_call(ins) || inst_return(ins))) { ins = db_get_value(brpc, sizeof(int), false); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); } #endif } if (db_run_mode == STEP_CONTINUE) { if (watchpt || db_find_breakpoint_here(pc)) { /* * Step over breakpoint/watchpoint. */ db_run_mode = STEP_INVISIBLE; db_set_single_step(regs); } else { db_set_breakpoints(); db_set_watchpoints(); } } else { db_set_single_step(regs); } }
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_restart_at_pc(boolean_t watchpt) { db_addr_t pc = PC_REGS(DDB_REGS); if ((db_run_mode == STEP_COUNT) || (db_run_mode == STEP_RETURN) || (db_run_mode == STEP_CALLT)) { db_expr_t ins __unused; /* seems used but gcc thinks not */ /* * We are about to execute this instruction, * so count it now. */ ins = db_get_value(pc, sizeof(int), FALSE); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); #ifdef SOFTWARE_SSTEP /* XXX works on mips, but... */ if (inst_branch(ins) || inst_call(ins)) { ins = db_get_value(next_instr_address(pc,1), sizeof(int), FALSE); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); } #endif /* SOFTWARE_SSTEP */ } if (db_run_mode == STEP_CONTINUE) { if (watchpt || db_find_breakpoint_here(pc)) { /* * Step over breakpoint/watchpoint. */ db_run_mode = STEP_INVISIBLE; db_set_single_step(DDB_REGS); } else { db_set_breakpoints(); db_set_watchpoints(); } } else { db_set_single_step(DDB_REGS); } }
boolean_t db_stop_at_pc(boolean_t *is_breakpoint) { db_addr_t pc; db_breakpoint_t bkpt; db_clear_single_step(DDB_REGS); db_clear_breakpoints(); db_clear_watchpoints(); 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 pc = PC_REGS(DDB_REGS); } #endif /* * Now check for a breakpoint at this address. */ bkpt = db_find_breakpoint_here(pc); if (bkpt) { if (--bkpt->count == 0) { bkpt->count = bkpt->init_count; *is_breakpoint = TRUE; return (TRUE); /* stop here */ } } else if (*is_breakpoint) { #ifdef __x86_64__ ddb_regs.tf_rip += 1; #endif } *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_printf("\t\t"); db_print_loc_and_inst(pc, DDB_REGS); db_printf("\n"); } return (FALSE); /* continue */ } } if (db_run_mode == STEP_RETURN) { db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); /* continue until matching return */ if (!inst_trap_return(ins) && (!inst_return(ins) || --db_call_depth != 0)) { if (db_sstep_print) { if (inst_call(ins) || inst_return(ins)) { int i; db_printf("[after %6d] ", db_inst_count); for (i = db_call_depth; --i > 0; ) db_printf(" "); db_print_loc_and_inst(pc, DDB_REGS); db_printf("\n"); } } if (inst_call(ins)) db_call_depth++; return (FALSE); /* continue */ } } if (db_run_mode == STEP_CALLT) { db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); /* continue until call or return */ if (!inst_call(ins) && !inst_return(ins) && !inst_trap_return(ins)) { return (FALSE); /* continue */ } } db_run_mode = STEP_NONE; return (TRUE); }
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); }
bool db_stop_at_pc(db_regs_t *regs, bool *is_breakpoint) { db_addr_t pc; db_breakpoint_t bkpt; pc = PC_REGS(regs); #ifdef FIXUP_PC_AFTER_BREAK if (*is_breakpoint) { /* * Breakpoint trap. Regardless if we treat this as a * real breakpoint (e.g. software single-step), fix up the PC. */ FIXUP_PC_AFTER_BREAK(regs); pc = PC_REGS(regs); } #endif #ifdef SOFTWARE_SSTEP /* * If we stopped at one of the single-step breakpoints, say it's not * really a breakpoint so that we don't skip over the real instruction. */ if (db_taken_bkpt.address == pc || db_not_taken_bkpt.address == pc) *is_breakpoint = false; #endif /* SOFTWARE_SSTEP */ db_clear_single_step(regs); db_clear_breakpoints(); db_clear_watchpoints(); /* * Now check for a breakpoint at this address. */ bkpt = db_find_breakpoint_here(pc); if (bkpt) { if (--bkpt->count == 0) { bkpt->count = bkpt->init_count; *is_breakpoint = true; return (true); /* stop here */ } } else if (*is_breakpoint) { #ifdef PC_ADVANCE PC_ADVANCE(regs); #else PC_REGS(regs) += BKPT_SIZE; #endif } *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_printf("\t\t"); db_print_loc_and_inst(pc); db_printf("\n"); } return (false); /* continue */ } } if (db_run_mode == STEP_RETURN) { db_expr_t ins = db_get_value(pc, sizeof(int), false); /* continue until matching return */ if (!inst_trap_return(ins) && (!inst_return(ins) || --db_call_depth != 0)) { if (db_sstep_print) { if (inst_call(ins) || inst_return(ins)) { int i; db_printf("[after %6d] ", db_inst_count); for (i = db_call_depth; --i > 0; ) db_printf(" "); db_print_loc_and_inst(pc); db_printf("\n"); } } if (inst_call(ins)) db_call_depth++; return (false); /* continue */ } } if (db_run_mode == STEP_CALLT) { db_expr_t ins = db_get_value(pc, sizeof(int), false); /* continue until call or return */ if (!inst_call(ins) && !inst_return(ins) && !inst_trap_return(ins)) { return (false); /* continue */ } } db_run_mode = STEP_NONE; return (true); }
boolean_t db_stop_at_pc(db_regs_t *regs, boolean_t *is_breakpoint) { db_addr_t pc, old_pc; db_breakpoint_t bkpt; db_clear_breakpoints(); db_clear_watchpoints(); old_pc = pc = PC_REGS(regs); #ifdef FIXUP_PC_AFTER_BREAK if (*is_breakpoint) { /* * Breakpoint trap. Fix up the PC if the * machine requires it. */ FIXUP_PC_AFTER_BREAK(regs); pc = PC_REGS(regs); } #endif /* * Now check for a breakpoint at this address. */ bkpt = db_find_breakpoint_here(pc); if (bkpt) { if (--bkpt->count == 0) { db_clear_single_step(regs); bkpt->count = bkpt->init_count; *is_breakpoint = TRUE; return (TRUE); /* stop here */ } } else if (*is_breakpoint #ifdef SOFTWARE_SSTEP && !((db_taken_bkpt && db_taken_bkpt->address == pc) || (db_not_taken_bkpt && db_not_taken_bkpt->address == pc)) #endif ) { #ifdef PC_ADVANCE PC_ADVANCE(regs); #else # ifdef SET_PC_REGS SET_PC_REGS(regs, old_pc); # else PC_REGS(regs) = old_pc; # endif #endif } db_clear_single_step(regs); *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_printf("\t\t"); db_print_loc_and_inst(pc); db_printf("\n"); } return (FALSE); /* continue */ } } if (db_run_mode == STEP_RETURN) { db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); /* continue until matching return */ if (!inst_trap_return(ins) && (!inst_return(ins) || --db_call_depth != 0)) { if (db_sstep_print) { if (inst_call(ins) || inst_return(ins)) { int i; db_printf("[after %6d] ", db_inst_count); for (i = db_call_depth; --i > 0; ) db_printf(" "); db_print_loc_and_inst(pc); db_printf("\n"); } } if (inst_call(ins)) db_call_depth++; return (FALSE); /* continue */ } } if (db_run_mode == STEP_CALLT) { db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); /* continue until call or return */ if (!inst_call(ins) && !inst_return(ins) && !inst_trap_return(ins)) { return (FALSE); /* continue */ } } db_run_mode = STEP_NONE; return (TRUE); }