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_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_set_single_step(db_regs_t *regs) { db_addr_t pc = PC_REGS(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)) { brpc = branch_taken(inst, pc, regs); 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); }
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_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_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); } }