static int kdb_ss(int argc, const char **argv) { int ssb = 0; struct pt_regs *regs = get_irq_regs(); ssb = (strcmp(argv[0], "ssb") == 0); if (argc != 0) return KDB_ARGCOUNT; if (!regs) { kdb_printf("%s: pt_regs not available\n", __FUNCTION__); return KDB_BADREG; } /* * Set trace flag and go. */ KDB_STATE_SET(DOING_SS); if (ssb) KDB_STATE_SET(DOING_SSB); kdba_setsinglestep(regs); /* Enable single step */ if (ssb) return KDB_CMD_SSB; return KDB_CMD_SS; }
kdb_dbtrap_t kdba_bp_trap(struct pt_regs *regs, int error_unused) { int i; kdb_dbtrap_t rv; kdb_bp_t *bp; if (KDB_NULL_REGS(regs)) return KDB_DB_NOBPT; /* * Determine which breakpoint was encountered. */ if (KDB_DEBUG(BP)) kdb_printf("kdba_bp_trap: rip=0x%lx (not adjusted) " "eflags=0x%lx ef=0x%p rsp=0x%lx\n", regs->rip, regs->eflags, regs, regs->rsp); rv = KDB_DB_NOBPT; /* Cause kdb() to return */ for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) { if (bp->bp_free) continue; if (!bp->bp_global && bp->bp_cpu != smp_processor_id()) continue; if ((void *)bp->bp_addr == (void *)(regs->rip - bp->bp_adjust)) { /* Hit this breakpoint. */ regs->rip -= bp->bp_adjust; kdb_printf("Instruction(i) breakpoint #%d at 0x%lx (adjusted)\n", i, regs->rip); kdb_id1(regs->rip); rv = KDB_DB_BPT; bp->bp_delay = 1; /* SSBPT is set when the kernel debugger must single * step a task in order to re-establish an instruction * breakpoint which uses the instruction replacement * mechanism. It is cleared by any action that removes * the need to single-step the breakpoint. */ KDB_STATE_SET(SSBPT); break; } } return rv; }
int kdb_stub(struct kgdb_state *ks) { int error = 0; kdb_bp_t *bp; unsigned long addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs); kdb_reason_t reason = KDB_REASON_OOPS; kdb_dbtrap_t db_result = KDB_DB_NOBPT; int i; if (KDB_STATE(REENTRY)) { reason = KDB_REASON_SWITCH; KDB_STATE_CLEAR(REENTRY); addr = instruction_pointer(ks->linux_regs); } ks->pass_exception = 0; if (atomic_read(&kgdb_setting_breakpoint)) reason = KDB_REASON_KEYBOARD; for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if ((bp->bp_enabled) && (bp->bp_addr == addr)) { reason = KDB_REASON_BREAK; db_result = KDB_DB_BPT; if (addr != instruction_pointer(ks->linux_regs)) kgdb_arch_set_pc(ks->linux_regs, addr); break; } } if (reason == KDB_REASON_BREAK || reason == KDB_REASON_SWITCH) { for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if (bp->bp_free) continue; if (bp->bp_addr == addr) { bp->bp_delay = 1; bp->bp_delayed = 1; /* * SSBPT is set when the kernel debugger must single step a * task in order to re-establish an instruction breakpoint * which uses the instruction replacement mechanism. It is * cleared by any action that removes the need to single-step * the breakpoint. */ reason = KDB_REASON_BREAK; db_result = KDB_DB_BPT; KDB_STATE_SET(SSBPT); break; } } } if (reason != KDB_REASON_BREAK && ks->ex_vector == 0 && ks->signo == SIGTRAP) { reason = KDB_REASON_SSTEP; db_result = KDB_DB_BPT; } /* Set initial kdb state variables */ KDB_STATE_CLEAR(KGDB_TRANS); kdb_initial_cpu = ks->cpu; kdb_current_task = kgdb_info[ks->cpu].task; kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo; /* Remove any breakpoints as needed by kdb and clear single step */ kdb_bp_remove(); KDB_STATE_CLEAR(DOING_SS); KDB_STATE_CLEAR(DOING_SSB); KDB_STATE_SET(PAGER); /* zero out any offline cpu data */ for_each_present_cpu(i) { if (!cpu_online(i)) { kgdb_info[i].debuggerinfo = NULL; kgdb_info[i].task = NULL; } } if (ks->err_code == DIE_OOPS || reason == KDB_REASON_OOPS) { ks->pass_exception = 1; KDB_FLAG_SET(CATASTROPHIC); } kdb_initial_cpu = ks->cpu; if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) { KDB_STATE_CLEAR(SSBPT); KDB_STATE_CLEAR(DOING_SS); } else { /* Start kdb main loop */ error = kdb_main_loop(KDB_REASON_ENTER, reason, ks->err_code, db_result, ks->linux_regs); } /* * Upon exit from the kdb main loop setup break points and restart * the system based on the requested continue state */ kdb_initial_cpu = -1; kdb_current_task = NULL; kdb_current_regs = NULL; KDB_STATE_CLEAR(PAGER); kdbnearsym_cleanup(); if (error == KDB_CMD_KGDB) { if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) { /* * This inteface glue which allows kdb to transition in into * the gdb stub. In order to do this the '?' or '' gdb serial * packet response is processed here. And then control is * passed to the gdbstub. */ if (KDB_STATE(DOING_KGDB)) gdbstub_state(ks, "?"); else gdbstub_state(ks, ""); KDB_STATE_CLEAR(DOING_KGDB); KDB_STATE_CLEAR(DOING_KGDB2); } return DBG_PASS_EVENT; } kdb_bp_install(ks->linux_regs); dbg_activate_sw_breakpoints(); /* Set the exit state to a single step or a continue */ if (KDB_STATE(DOING_SS)) gdbstub_state(ks, "s"); else gdbstub_state(ks, "c"); KDB_FLAG_CLEAR(CATASTROPHIC); /* Invoke arch specific exception handling prior to system resume */ kgdb_info[ks->cpu].ret_state = gdbstub_state(ks, "e"); if (ks->pass_exception) kgdb_info[ks->cpu].ret_state = 1; if (error == KDB_CMD_CPU) { KDB_STATE_SET(REENTRY); /* * Force clear the single step bit because kdb emulates this * differently vs the gdbstub */ kgdb_single_step = 0; dbg_deactivate_sw_breakpoints(); return DBG_SWITCH_CPU_EVENT; } return kgdb_info[ks->cpu].ret_state; }
static void kdb_setsinglestep(struct pt_regs *regs) { KDB_STATE_SET(DOING_SS); }