static int or1k_debug_entry(struct target *target) { LOG_DEBUG("-"); int retval = or1k_save_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_save_context"); return retval; } struct or1k_common *or1k = target_to_or1k(target); uint32_t addr = or1k->core_regs[OR1K_REG_NPC]; if (breakpoint_find(target, addr)) /* Halted on a breakpoint, step back to permit executing the instruction there */ retval = or1k_set_core_reg(&or1k->core_cache->reg_list[OR1K_REG_NPC], (uint8_t *)&addr); return retval; }
int lakemont_resume(struct target *t, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct breakpoint *bp = NULL; struct x86_32_common *x86_32 = target_to_x86_32(t); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; /* TODO lakemont_enable_breakpoints(t); */ if (t->state == TARGET_HALTED) { /* running away for a software breakpoint needs some special handling */ uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32); bp = breakpoint_find(t, eip); if (bp != NULL /*&& bp->type == BKPT_SOFT*/) { /* the step will step over the breakpoint */ if (lakemont_step(t, 0, 0, 1) != ERROR_OK) { LOG_ERROR("%s stepping over a software breakpoint at 0x%08" PRIx32 " " "failed to resume the target", __func__, eip); return ERROR_FAIL; } } /* if breakpoints are enabled, we need to redirect these into probe mode */ struct breakpoint *activeswbp = t->breakpoints; while (activeswbp != NULL && activeswbp->set == 0) activeswbp = activeswbp->next; struct watchpoint *activehwbp = t->watchpoints; while (activehwbp != NULL && activehwbp->set == 0) activehwbp = activehwbp->next; if (activeswbp != NULL || activehwbp != NULL) buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1); if (do_resume(t) != ERROR_OK) return ERROR_FAIL; } else { LOG_USER("target not halted"); return ERROR_FAIL; } return ERROR_OK; }
static int avr32_ap7k_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); struct breakpoint *breakpoint = NULL; uint32_t resume_pc; int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) { target_free_all_working_areas(target); /* avr32_ap7k_enable_breakpoints(target); avr32_ap7k_enable_watchpoints(target); */ } /* current = 1: continue on current pc, otherwise continue at <address> */ if (!current) { #if 0 if (retval != ERROR_OK) return retval; #endif } resume_pc = buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32); avr32_ap7k_restore_context(target); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); #if 0 avr32_ap7k_unset_breakpoint(target, breakpoint); avr32_ap7k_single_step_core(target); avr32_ap7k_set_breakpoint(target, breakpoint); #endif } } #if 0 /* enable interrupts if we are running */ avr32_ap7k_enable_interrupts(target, !debug_execution); /* exit debug mode */ mips_ejtag_exit_debug(ejtag_info); #endif retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR); if (retval != ERROR_OK) return retval; retval = avr32_jtag_exec(&ap7k->jtag, RETD); if (retval != ERROR_OK) return retval; target->debug_reason = DBG_REASON_NOTHALTED; /* registers are now invalid */ register_cache_invalidate(ap7k->core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc); } return ERROR_OK; }
static int or1k_resume_or_step(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution, int step) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); struct breakpoint *breakpoint = NULL; uint32_t resume_pc; uint32_t debug_reg_list[OR1K_DEBUG_REG_NUM]; LOG_DEBUG("Addr: 0x%" PRIx32 ", stepping: %s, handle breakpoints %s\n", address, step ? "yes" : "no", handle_breakpoints ? "yes" : "no"); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) target_free_all_working_areas(target); /* current ? continue on current pc : continue at <address> */ if (!current) buf_set_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32, address); int retval = or1k_restore_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_restore_context"); return retval; } /* read debug registers (starting from DMR1 register) */ retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); if (retval != ERROR_OK) { LOG_ERROR("Error while reading debug registers"); return retval; } /* Clear Debug Reason Register (DRR) */ debug_reg_list[OR1K_DEBUG_REG_DRR] = 0; /* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) */ debug_reg_list[OR1K_DEBUG_REG_DMR2] &= ~OR1K_DMR2_WGB; if (step) /* Set the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] |= OR1K_DMR1_ST | OR1K_DMR1_BT; else /* Clear the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] &= ~(OR1K_DMR1_ST | OR1K_DMR1_BT); /* Set traps to be handled by the debug unit in the Debug Stop Register (DSR). Check if we have any software breakpoints in place before setting this value - the kernel, for instance, relies on l.trap instructions not stalling the processor ! */ if (is_any_soft_breakpoint(target) == true) debug_reg_list[OR1K_DEBUG_REG_DSR] |= OR1K_DSR_TE; /* Write debug registers (starting from DMR1 register) */ retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); if (retval != ERROR_OK) { LOG_ERROR("Error while writing back debug registers"); return retval; } resume_pc = buf_get_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32); /* The front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("Unset breakpoint at 0x%08" PRIx32, breakpoint->address); retval = or1k_remove_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; } } /* Unstall time */ retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_UNSTALL); if (retval != ERROR_OK) { LOG_ERROR("Error while unstalling the CPU"); return retval; } if (step) target->debug_reason = DBG_REASON_SINGLESTEP; else target->debug_reason = DBG_REASON_NOTHALTED; /* Registers are now invalid */ register_cache_invalidate(or1k->core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("Target resumed at 0x%08" PRIx32, resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("Target debug resumed at 0x%08" PRIx32, resume_pc); } return ERROR_OK; }
static VALUE Breakpoint_find(VALUE self, VALUE breakpoints, VALUE source, VALUE pos) { return breakpoint_find(breakpoints, source, pos); }
int lakemont_poll(struct target *t) { /* LMT1 PMCR register currently allows code breakpoints, data breakpoints, * single stepping and shutdowns to be redirected to PM but does not allow * redirecting into PM as a result of SMM enter and SMM exit */ uint32_t ts = get_tapstatus(t); if (ts == 0xFFFFFFFF && t->state != TARGET_DEBUG_RUNNING) { /* something is wrong here */ LOG_ERROR("tapstatus invalid - scan_chain serialization or locked JTAG access issues"); /* TODO: Give a hint that unlocking is wrong or maybe a * 'jtag arp_init' helps */ t->state = TARGET_DEBUG_RUNNING; return ERROR_OK; } if ((!(ts & TS_PM_BIT))) { if (t->state == TARGET_HALTED) { LOG_USER("target running for unknown reason"); } else if (t->state == TARGET_DEBUG_RUNNING) { LOG_USER("Debug running tapstatus=0x%08" PRIx32, ts); } LOG_DEBUG("tapstatus=0x%08" PRIx32, ts); t->state = TARGET_RUNNING; } if (t->state == TARGET_RUNNING || t->state == TARGET_DEBUG_RUNNING) { if (ts & TS_PM_BIT) { LOG_USER("redirect to PM, tapstatus=0x%08" PRIx32, get_tapstatus(t)); t->state = TARGET_DEBUG_RUNNING; if (save_context(t) != ERROR_OK) return ERROR_FAIL; if (halt_prep(t) != ERROR_OK) return ERROR_FAIL; t->state = TARGET_HALTED; t->debug_reason = DBG_REASON_UNDEFINED; struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32); uint32_t dr6 = buf_get_u32(x86_32->cache->reg_list[DR6].value, 0, 32); uint32_t hwbreakpoint = (uint32_t)-1; if (dr6 & DR6_BRKDETECT_0) hwbreakpoint = 0; if (dr6 & DR6_BRKDETECT_1) hwbreakpoint = 1; if (dr6 & DR6_BRKDETECT_2) hwbreakpoint = 2; if (dr6 & DR6_BRKDETECT_3) hwbreakpoint = 3; if (hwbreakpoint != (uint32_t)-1) { uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32); uint32_t type = dr7 & (0x03 << (DR7_RW_SHIFT + hwbreakpoint*DR7_RW_LEN_SIZE)); if (type == DR7_BP_EXECUTE) { LOG_USER("hit hardware breakpoint (hwreg=%" PRIu32 ") at 0x%08" PRIx32, hwbreakpoint, eip); } else { uint32_t address = 0; switch (hwbreakpoint) { default: case 0: address = buf_get_u32(x86_32->cache->reg_list[DR0].value, 0, 32); break; case 1: address = buf_get_u32(x86_32->cache->reg_list[DR1].value, 0, 32); break; case 2: address = buf_get_u32(x86_32->cache->reg_list[DR2].value, 0, 32); break; case 3: address = buf_get_u32(x86_32->cache->reg_list[DR3].value, 0, 32); break; } LOG_USER("hit '%s' watchpoint for 0x%08" PRIx32 " (hwreg=%" PRIu32 ") at 0x%08" PRIx32, type == DR7_BP_WRITE ? "write" : "access", address, hwbreakpoint, eip); } t->debug_reason = DBG_REASON_BREAKPOINT; } else { /* Check if the target hit a software breakpoint. * ! Watch out: EIP is currently pointing after the breakpoint opcode */ struct breakpoint *bp = NULL; bp = breakpoint_find(t, eip-1); if (bp != NULL) { t->debug_reason = DBG_REASON_BREAKPOINT; if (bp->type == BKPT_SOFT) { /* The EIP is now pointing the the next byte after the * breakpoint instruction. This needs to be corrected. */ buf_set_u32(x86_32->cache->reg_list[EIP].value, 0, 32, eip-1); x86_32->cache->reg_list[EIP].dirty = 1; x86_32->cache->reg_list[EIP].valid = 1; LOG_USER("hit software breakpoint at 0x%08" PRIx32, eip-1); } else { /* it's not a hardware breakpoint (checked already in DR6 state) * and it's also not a software breakpoint ... */ LOG_USER("hit unknown breakpoint at 0x%08" PRIx32, eip); } } else { /* There is also the case that we hit an breakpoint instruction, * which was not set by us. This needs to be handled be the * application that introduced the breakpoint. */ LOG_USER("unknown break reason at 0x%08" PRIx32, eip); } } return target_call_event_callbacks(t, TARGET_EVENT_HALTED); } } return ERROR_OK; }
int lakemont_step(struct target *t, int current, uint32_t address, int handle_breakpoints) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32); uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32); uint32_t pmcr = buf_get_u32(x86_32->cache->reg_list[PMCR].value, 0, 32); struct breakpoint *bp = NULL; int retval = ERROR_OK; uint32_t tapstatus = 0; if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; bp = breakpoint_find(t, eip); if (retval == ERROR_OK && bp != NULL/*&& bp->type == BKPT_SOFT*/) { /* TODO: This should only be done for software breakpoints. * Stepping from hardware breakpoints should be possible with the resume flag * Needs testing. */ retval = x86_32_common_remove_breakpoint(t, bp); } /* Set EFLAGS[TF] and PMCR[IR], exit pm and wait for PRDY# */ LOG_DEBUG("modifying PMCR = 0x%08" PRIx32 " and EFLAGS = 0x%08" PRIx32, pmcr, eflags); eflags = eflags | (EFLAGS_TF | EFLAGS_RF); buf_set_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32, eflags); buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1); LOG_DEBUG("EFLAGS [TF] [RF] bits set=0x%08" PRIx32 ", PMCR=0x%08" PRIx32 ", EIP=0x%08" PRIx32, eflags, pmcr, eip); tapstatus = get_tapstatus(t); t->debug_reason = DBG_REASON_SINGLESTEP; t->state = TARGET_DEBUG_RUNNING; if (restore_context(t) != ERROR_OK) return ERROR_FAIL; if (exit_probemode(t) != ERROR_OK) return ERROR_FAIL; target_call_event_callbacks(t, TARGET_EVENT_RESUMED); tapstatus = get_tapstatus(t); if (tapstatus & (TS_PM_BIT | TS_EN_PM_BIT | TS_PRDY_BIT | TS_PMCR_BIT)) { /* target has stopped */ if (save_context(t) != ERROR_OK) return ERROR_FAIL; if (halt_prep(t) != ERROR_OK) return ERROR_FAIL; t->state = TARGET_HALTED; LOG_USER("step done from EIP 0x%08" PRIx32 " to 0x%08" PRIx32, eip, buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32)); target_call_event_callbacks(t, TARGET_EVENT_HALTED); } else { /* target didn't stop * I hope the poll() will catch it, but the deleted breakpoint is gone */ LOG_ERROR("%s target didn't stop after executing a single step", __func__); t->state = TARGET_RUNNING; return ERROR_FAIL; } /* try to re-apply the breakpoint, even of step failed * TODO: When a bp was set, we should try to stop the target - fix the return above */ if (bp != NULL/*&& bp->type == BKPT_SOFT*/) { /* TODO: This should only be done for software breakpoints. * Stepping from hardware breakpoints should be possible with the resume flag * Needs testing. */ retval = x86_32_common_add_breakpoint(t, bp); } return retval; }
static int or1k_resume_or_step(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution, int step) { struct or1k_common *or1k = target_to_or1k(target); struct breakpoint *breakpoint = NULL; uint32_t resume_pc; int retval; LOG_DEBUG(" - "); LOG_DEBUG(" addr: 0x%x, stepping: %d, handle breakpoints %d\n", address, step, handle_breakpoints); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) { target_free_all_working_areas(target); } /* current ? continue on current pc : continue at <address> */ if (!current) { buf_set_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32, address); } if (!step) { or1k_restore_context(target); } uint32_t debug_reg_list[OR1K_DEBUG_REG_NUM]; /* read debug registers (starting from DMR1 register) */ or1k_jtag_read_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); /* Clear Debug Reason Register (DRR) */ debug_reg_list[OR1K_DEBUG_REG_DRR] = 0; /* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) */ debug_reg_list[OR1K_DEBUG_REG_DMR2] &= ~OR1K_DMR2_WGB; if (step) /* Set the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] |= OR1K_DMR1_ST | OR1K_DMR1_BT; else /* Clear the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] &= ~(OR1K_DMR1_ST | OR1K_DMR1_BT); /* Set traps to be handled by the debug unit in the Debug Stop Register (DSR) */ /* TODO - check if we have any software breakpoints in place before setting this value - the kernel, for instance, relies on l.trap instructions not stalling the processor! */ debug_reg_list[OR1K_DEBUG_REG_DSR] |= OR1K_DSR_TE; /* write debug registers (starting from DMR1 register) */ or1k_jtag_write_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); resume_pc = buf_get_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ if ((breakpoint = breakpoint_find(target, resume_pc))) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); #if 0 /* Do appropriate things here to remove breakpoint. */ #endif } } /* Unstall time */ /* Mohor debug if, clearing control register unstalls */ retval = or1k_jtag_write_cpu_cr(&or1k->jtag, 0, 0); if (retval != ERROR_OK) return retval; if (step) target->debug_reason = DBG_REASON_SINGLESTEP; else target->debug_reason = DBG_REASON_NOTHALTED; /* registers are now invalid */ register_cache_invalidate(or1k->core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc); } return ERROR_OK; }