void kdb_bp_install_local(struct pt_regs *regs) { int i; for(i=0; i<KDB_MAXBPT; i++) { kdb_bp_t *bp = &kdb_breakpoints[i]; if (KDB_DEBUG(BP)) { kdb_printf("kdb_bp_install_local bp %d bp_enabled %d bp_global %d cpu %d bp_cpu %d\n", i, bp->bp_enabled, bp->bp_global, smp_processor_id(), bp->bp_cpu); } if (kdb_is_installable_local_bp(bp)) kdba_installbp(regs, bp); } }
void kdb_bp_install_global(struct pt_regs *regs) { int i; for(i=0; i<KDB_MAXBPT; i++) { kdb_bp_t *bp = &kdb_breakpoints[i]; if (KDB_DEBUG(BP)) { kdb_printf("kdb_bp_install_global bp %d bp_enabled %d bp_global %d\n", i, bp->bp_enabled, bp->bp_global); } /* HW BP local or global are installed in kdb_bp_install_local*/ if (kdb_is_installable_global_bp(bp)) kdba_installbp(regs, bp); } }
kdb_dbtrap_t kdba_db_trap(struct pt_regs *regs, int error_unused) { kdb_machreg_t dr6; kdb_machreg_t dr7; int rw, reg; int i; kdb_dbtrap_t rv = KDB_DB_BPT; kdb_bp_t *bp; if (KDB_NULL_REGS(regs)) return KDB_DB_NOBPT; dr6 = kdba_getdr6(); dr7 = kdba_getdr7(); if (KDB_DEBUG(BP)) kdb_printf("kdb: dr6 0x%lx dr7 0x%lx\n", dr6, dr7); if (dr6 & DR6_BS) { if (KDB_STATE(SSBPT)) { if (KDB_DEBUG(BP)) kdb_printf("ssbpt\n"); KDB_STATE_CLEAR(SSBPT); for(i=0,bp=kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if (KDB_DEBUG(BP)) kdb_printf("bp 0x%p enabled %d delayed %d global %d cpu %d\n", bp, bp->bp_enabled, bp->bp_delayed, bp->bp_global, bp->bp_cpu); if (!bp->bp_enabled) continue; if (!bp->bp_global && bp->bp_cpu != smp_processor_id()) continue; if (KDB_DEBUG(BP)) kdb_printf("bp for this cpu\n"); if (bp->bp_delayed) { bp->bp_delayed = 0; if (KDB_DEBUG(BP)) kdb_printf("kdba_installbp\n"); kdba_installbp(regs, bp); if (!KDB_STATE(DOING_SS)) { regs->eflags &= ~EF_TF; return(KDB_DB_SSBPT); } break; } } if (i == KDB_MAXBPT) { kdb_printf("kdb: Unable to find delayed breakpoint\n"); } if (!KDB_STATE(DOING_SS)) { regs->eflags &= ~EF_TF; return(KDB_DB_NOBPT); } /* FALLTHROUGH */ } /* * KDB_STATE_DOING_SS is set when the kernel debugger is using * the processor trap flag to single-step a processor. If a * single step trap occurs and this flag is clear, the SS trap * will be ignored by KDB and the kernel will be allowed to deal * with it as necessary (e.g. for ptrace). */ if (!KDB_STATE(DOING_SS)) goto unknown; /* single step */ rv = KDB_DB_SS; /* Indicate single step */ if (KDB_STATE(DOING_SSB)) { unsigned char instruction[2]; kdb_id1(regs->rip); if (kdb_getarea(instruction, regs->rip) || (instruction[0]&0xf0) == 0xe0 || /* short disp jumps */ (instruction[0]&0xf0) == 0x70 || /* Misc. jumps */ instruction[0] == 0xc2 || /* ret */ instruction[0] == 0x9a || /* call */ (instruction[0]&0xf8) == 0xc8 || /* enter, leave, iret, int, */ ((instruction[0] == 0x0f) && ((instruction[1]&0xf0)== 0x80)) ) { /* * End the ssb command here. */ KDB_STATE_CLEAR(DOING_SSB); KDB_STATE_CLEAR(DOING_SS); } else { rv = KDB_DB_SSB; /* Indicate ssb - dismiss immediately */ } } else { /* * Print current insn */ kdb_printf("SS trap at "); kdb_symbol_print(regs->rip, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE); kdb_id1(regs->rip); KDB_STATE_CLEAR(DOING_SS); } if (rv != KDB_DB_SSB) regs->eflags &= ~EF_TF; } if (dr6 & DR6_B0) { rw = DR7_RW0(dr7); reg = 0; goto handle; } if (dr6 & DR6_B1) { rw = DR7_RW1(dr7); reg = 1; goto handle; } if (dr6 & DR6_B2) { rw = DR7_RW2(dr7); reg = 2; goto handle; } if (dr6 & DR6_B3) { rw = DR7_RW3(dr7); reg = 3; goto handle; } if (rv > 0) goto handled; goto unknown; /* dismiss */ handle: /* * Set Resume Flag */ regs->eflags |= EF_RF; /* * Determine which breakpoint was encountered. */ for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) { if (!(bp->bp_free) && (bp->bp_global || bp->bp_cpu == smp_processor_id()) && (bp->bp_hard) && (bp->bp_hard->bph_reg == reg)) { /* * Hit this breakpoint. */ kdb_printf("%s breakpoint #%d at " kdb_bfd_vma_fmt "\n", kdba_rwtypes[rw], i, bp->bp_addr); /* * For an instruction breakpoint, disassemble * the current instruction. */ if (rw == 0) { kdb_id1(regs->rip); } goto handled; } } unknown: regs->eflags |= EF_RF; /* Supress further faults */ rv = KDB_DB_NOBPT; /* Cause kdb() to return */ handled: /* * Clear the pending exceptions. */ kdba_putdr6(0); return rv; }