Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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);
	}
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
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);
}