void db_set_single_step(db_regs_t *regs) { db_addr_t pc = PC_REGS(regs); #ifndef SOFTWARE_SSTEP_EMUL db_addr_t brpc; u_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, getreg_val, regs); if (brpc != pc) { /* self-branches are hopeless */ db_taken_bkpt = db_set_temp_breakpoint(brpc); } #if 0 /* XXX this seems like a true bug, no? */ pc = next_instr_address(pc, 1); #endif } #endif /*SOFTWARE_SSTEP_EMUL*/ pc = next_instr_address(pc, 0); db_not_taken_bkpt = db_set_temp_breakpoint(pc); }
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_single_step(void) { db_addr_t pc = PC_REGS(), brpc; unsigned 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); if (brpc != pc) { /* self-branches are hopeless */ db_taken_bkpt = db_set_temp_breakpoint(brpc); } pc = next_instr_address(pc, 1); } pc = next_instr_address(pc, 0); db_not_taken_bkpt = db_set_temp_breakpoint(pc); }
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); }