static int emul_sstep_put(char *put_str, char *arg) { if (!arch_needs_sstep_emulation) { char *ptr = &put_str[11]; if (put_str[1] != 'T' || put_str[2] != '0') return 1; kgdb_hex2long(&ptr, &sstep_thread_id); return 0; } switch (sstep_state) { case 1: /* validate the "g" packet to get the IP */ kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs, NUMREGBYTES); gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs); v2printk("Stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs)); /* Want to stop at IP + break instruction size by default */ sstep_addr = cont_addr + BREAK_INSTR_SIZE; break; case 2: if (strncmp(put_str, "$OK", 3)) { eprintk("kgdbts: failed sstep break set\n"); return 1; } break; case 3: if (strncmp(put_str, "$T0", 3)) { eprintk("kgdbts: failed continue sstep\n"); return 1; } else { char *ptr = &put_str[11]; kgdb_hex2long(&ptr, &sstep_thread_id); } break; case 4: if (strncmp(put_str, "$OK", 3)) { eprintk("kgdbts: failed sstep break unset\n"); return 1; } /* Single step is complete so continue on! */ sstep_state = 0; return 0; default: eprintk("kgdbts: ERROR failed sstep put emulation\n"); } /* Continue on the same test line until emulation is complete */ ts.idx--; return 0; }
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, char *remcomInBuffer, char *remcomOutBuffer, struct pt_regs *linux_regs) { unsigned long addr; char *ptr; switch (remcomInBuffer[0]) { case 'c': /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcomInBuffer[1]; if (kgdb_hex2long(&ptr, &addr)) { linux_regs->pc = addr; linux_regs->npc = addr + 4; } /* fallthru */ case 'D': case 'k': if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) { linux_regs->pc = linux_regs->npc; linux_regs->npc += 4; } return 0; } return -1; }
int kgdb_arch_handle_exception(int exception_vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *linux_regs) { unsigned long addr; char *ptr; switch (remcom_in_buffer[0]) { case 'D': case 'k': case 'c': /* * Try to read optional parameter, pc unchanged if no parm. * If this was a compiled breakpoint, we need to move * to the next instruction or we will just breakpoint * over and over again. */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) linux_regs->ARM_pc = addr; else if (compiled_break == 1) linux_regs->ARM_pc += 4; compiled_break = 0; return 0; } return -1; }
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, char *remcomInBuffer, char *remcomOutBuffer, struct pt_regs *regs) { unsigned long addr; char *ptr; undo_single_step(regs); switch (remcomInBuffer[0]) { case 's': case 'c': ptr = &remcomInBuffer[1]; if (kgdb_hex2long(&ptr, &addr)) regs->ret = addr; case 'D': case 'k': atomic_set(&kgdb_cpu_doing_single_step, -1); if (remcomInBuffer[0] == 's') { do_single_step(regs); atomic_set(&kgdb_cpu_doing_single_step, smp_processor_id()); } return 0; } return -1; }
/* * Handle the 's' and 'c' commands */ int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *regs) { char *ptr; unsigned long address; int cpu = smp_processor_id(); switch (remcom_in_buffer[0]) { case 's': case 'c': /* handle the optional parameter */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &address)) regs->cp0_epc = address; atomic_set(&kgdb_cpu_doing_single_step, -1); if (remcom_in_buffer[0] == 's') atomic_set(&kgdb_cpu_doing_single_step, cpu); return 0; } return -1; }
/* * Handle unknown packets and [CcsDk] packets * - at this point breakpoints have been installed */ int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *regs) { long addr; char *ptr; switch (remcom_in_buffer[0]) { case 'c': case 's': /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) regs->pc = addr; case 'D': case 'k': atomic_set(&kgdb_cpu_doing_single_step, -1); if (remcom_in_buffer[0] == 's') { kgdb_arch_do_singlestep(regs); kgdb_single_step = 1; atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); } return 0; } return -1; /* this means that we do not want to exit from the handler */ }
int kgdb_arch_handle_exception(int exception_vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *linux_regs) { unsigned long addr; char *ptr; switch (remcom_in_buffer[0]) { case 'D': case 'k': case 'c': ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) linux_regs->ARM_pc = addr; else if (compiled_break == 1) linux_regs->ARM_pc += 4; compiled_break = 0; return 0; } return -1; }
static int get_thread_id_continue(char *put_str, char *arg) { char *ptr = &put_str[11]; if (put_str[1] != 'T' || put_str[2] != '0') return 1; kgdb_hex2long(&ptr, &cont_thread_id); return 0; }
int kgdb_arch_handle_exception(int exceptionVector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *linux_regs) { long addr; long breakno; char *ptr; int newPC; int wp_status; switch (remcom_in_buffer[0]) { case 'c': case 's': if (kgdb_contthread && kgdb_contthread != current) { strcpy(remcom_out_buffer, "E00"); break; } kgdb_contthread = NULL; /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) { linux_regs->retx = addr; } newPC = linux_regs->retx; /* clear the trace bit */ linux_regs->syscfg &= 0xfffffffe; /* set the trace bit if we're stepping */ if (remcom_in_buffer[0] == 's') { linux_regs->syscfg |= 0x1; debugger_step = 1; } wp_status = bfin_read_WPSTAT(); CSYNC(); if (exceptionVector == VEC_WATCH) { for (breakno = 0; breakno < 6; ++breakno) { if (wp_status & (1 << breakno)) { breakinfo->skip = 1; break; } } } kgdb_correct_hw_break(); bfin_write_WPSTAT(0); return 0; } /* switch */ return -1; /* this means that we do not want to exit from the handler */ }
static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs, struct unw_frame_info *info, unsigned long *reg, struct ia64_fpreg *freg, int rw) { int result = 1; if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127))) return 0; switch (regnum) { case IA64_FR0_REGNUM + 6: case IA64_FR0_REGNUM + 7: case IA64_FR0_REGNUM + 8: case IA64_FR0_REGNUM + 9: case IA64_FR0_REGNUM + 10: case IA64_FR0_REGNUM + 11: case IA64_FR0_REGNUM + 12: if (rw) { #ifndef XEN char *ptr = inbuffer; freg->u.bits[0] = *reg; kgdb_hex2long(&ptr, &freg->u.bits[1]); *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) = *freg; #else printk("%s: %d: writing to fpreg is not supported.\n", __func__, __LINE__); #endif break; } else if (!ptregs) result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, freg, rw); else #ifndef XEN *freg = *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))); #else //XXX struct ia64_fpreg and struct pt_fpreg are same. *freg = *((struct ia64_fpreg*)(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6)))); #endif break; default: if (!rw) result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, freg, rw); else result = 0; break; } return result; }
/** * kgdb_arch_handle_exception - Handle architecture specific GDB packets. * @vector: The error vector of the exception that happened. * @signo: The signal number of the exception that happened. * @err_code: The error code of the exception that happened. * @remcom_in_buffer: The buffer of the packet we have read. * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into. * @regs: The &struct pt_regs of the current process. * * This function MUST handle the 'c' and 's' command packets, * as well packets to set / remove a hardware breakpoint, if used. * If there are additional packets which the hardware needs to handle, * they are handled here. The code should return -1 if it wants to * process more packets, and a %0 or %1 if it wants to exit from the * kgdb callback. */ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, char *remcomInBuffer, char *remcomOutBuffer, struct pt_regs *linux_regs) { unsigned long addr; unsigned long dr6; char *ptr; int newPC; switch (remcomInBuffer[0]) { case 'c': case 's': /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcomInBuffer[1]; if (kgdb_hex2long(&ptr, &addr)) linux_regs->ip = addr; case 'D': case 'k': newPC = linux_regs->ip; /* clear the trace bit */ linux_regs->flags &= ~X86_EFLAGS_TF; atomic_set(&kgdb_cpu_doing_single_step, -1); /* set the trace bit if we're stepping */ if (remcomInBuffer[0] == 's') { linux_regs->flags |= X86_EFLAGS_TF; atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); } get_debugreg(dr6, 6); if (!(dr6 & 0x4000)) { int breakno; for (breakno = 0; breakno < 4; breakno++) { if (dr6 & (1 << breakno) && breakinfo[breakno].type == 0) { /* Set restore flag: */ linux_regs->flags |= X86_EFLAGS_RF; break; } } } set_debugreg(0UL, 6); kgdb_correct_hw_break(); return 0; } /* this means that we do not want to exit from the handler: */ return -1; }
/* Write memory due to an 'M' or 'X' packet. */ static int write_mem_msg(int binary) { char *ptr = &remcom_in_buffer[1]; unsigned long addr; unsigned long length; int err; if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' && kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') { if (binary) err = kgdb_ebin2mem(ptr, (char *)addr, length); else err = kgdb_hex2mem(ptr, (char *)addr, length); if (err) return err; if (CACHE_FLUSH_IS_SAFE) flush_icache_range(addr, addr + length); return 0; } return -EINVAL; }
static void kgdb_arch_update_addr(struct pt_regs *regs, char *remcom_in_buffer) { unsigned long addr; char *ptr; ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) kgdb_arch_set_pc(regs, addr); else if (compiled_break == 1) kgdb_arch_set_pc(regs, regs->pc + 4); compiled_break = 0; }
int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *regs) { long addr; char *ptr; int newPC; int i; switch (remcom_in_buffer[0]) { case 'c': case 's': if (kgdb_contthread && kgdb_contthread != current) { strcpy(remcom_out_buffer, "E00"); break; } kgdb_contthread = NULL; /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) { regs->retx = addr; } newPC = regs->retx; /* clear the trace bit */ regs->syscfg &= 0xfffffffe; /* set the trace bit if we're stepping */ if (remcom_in_buffer[0] == 's') { regs->syscfg |= 0x1; kgdb_single_step = regs->ipend; kgdb_single_step >>= 6; for (i = 10; i > 0; i--, kgdb_single_step >>= 1) if (kgdb_single_step & 1) break; /* i indicate event priority of current stopped instruction * user space instruction is 0, IVG15 is 1, IVTMR is 10. * kgdb_single_step > 0 means in single step mode */ kgdb_single_step = i + 1; } bfin_correct_hw_break(); return 0; } /* switch */
int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *regs) { char *ptr; unsigned long addr; switch (remcom_in_buffer[0]) { case 's': case 'c': /* handle the optional parameters */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) regs->ea = addr; return 0; } return -1; /* this means that we do not want to exit from the handler */ }
/* * kgdb_arch_handle_exception - Handle architecture specific GDB packets. * @vector: The error vector of the exception that happened. * @signo: The signal number of the exception that happened. * @err_code: The error code of the exception that happened. * @remcom_in_buffer: The buffer of the packet we have read. * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into. * @regs: The &struct pt_regs of the current process. * * This function MUST handle the 'c' and 's' command packets, * as well packets to set / remove a hardware breakpoint, if used. * If there are additional packets which the hardware needs to handle, * they are handled here. The code should return -1 if it wants to * process more packets, and a %0 or %1 if it wants to exit from the * kgdb callback. */ int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *regs) { char *ptr; unsigned long address; /* Undo any stepping we may have done. */ undo_single_step(regs); switch (remcom_in_buffer[0]) { case 'c': case 's': case 'D': case 'k': /* * Try to read optional parameter, pc unchanged if no parm. * If this was a compiled-in breakpoint, we need to move * to the next instruction or we will just breakpoint * over and over again. */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &address)) regs->pc = address; else if (*(unsigned long *)regs->pc == compiled_bpt) regs->pc += BREAK_INSTR_SIZE; if (remcom_in_buffer[0] == 's') { do_single_step(regs); kgdb_single_step = 1; atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); } else atomic_set(&kgdb_cpu_doing_single_step, -1); return 0; } return -1; /* this means that we do not want to exit from the handler */ }
/* * This function does PowerPC specific processing for interfacing to gdb. */ int kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *linux_regs) { char *ptr = &remcom_in_buffer[1]; unsigned long addr; switch (remcom_in_buffer[0]) { /* * sAA..AA Step one instruction from AA..AA * This will return an error to gdb .. */ case 's': case 'c': /* handle the optional parameter */ if (kgdb_hex2long (&ptr, &addr)) linux_regs->nip = addr; atomic_set(&cpu_doing_single_step, -1); /* set the trace bit if we're stepping */ if (remcom_in_buffer[0] == 's') { #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); linux_regs->msr |= MSR_DE; #else linux_regs->msr |= MSR_SE; #endif debugger_step = 1; if (kgdb_contthread) atomic_set(&cpu_doing_single_step, smp_processor_id()); } return 0; } return -1; }
void kgdb_put_reg(char *inbuffer, char *outbuffer, int regnum, struct unw_frame_info *info, struct pt_regs *ptregs) { unsigned long reg; char nat = 0; struct ia64_fpreg freg; int i; char *ptr; ptr = inbuffer; kgdb_hex2long(&ptr, ®); strcpy(outbuffer, "OK"); if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) || (regnum >= (IA64_GR0_REGNUM + 4) && regnum <= (IA64_GR0_REGNUM + 7)) || (regnum >= (IA64_GR0_REGNUM + 16) && regnum <= (IA64_GR0_REGNUM + 31))) { unw_access_gr(info, regnum - IA64_GR0_REGNUM, ®, &nat, 1); } else if ((regnum >= (IA64_GR0_REGNUM + 2) && regnum <= (IA64_GR0_REGNUM + 3)) || (regnum >= (IA64_GR0_REGNUM + 8) && regnum <= (IA64_GR0_REGNUM + 15))) { for (i = 0; i < (sizeof(gr_reg_to_ptreg_index) / sizeof(gr_reg_to_ptreg_index[0])); i++) if (gr_reg_to_ptreg_index[0].reg == regnum) { *((unsigned long *) (((void *)ptregs) + gr_reg_to_ptreg_index[i].ptregoff)) = reg; break; } } else if (regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)) switch (regnum) { case IA64_BR0_REGNUM: case IA64_BR0_REGNUM + 6: case IA64_BR0_REGNUM + 7: for (i = 0; i < (sizeof(br_reg_to_ptreg_index) / sizeof(br_reg_to_ptreg_index[0])); i++) if (br_reg_to_ptreg_index[i].reg == regnum) { *((unsigned long *) (((void *)ptregs) + br_reg_to_ptreg_index[i].ptregoff)) = reg; break; } break; case IA64_BR0_REGNUM + 1: case IA64_BR0_REGNUM + 2: case IA64_BR0_REGNUM + 3: case IA64_BR0_REGNUM + 4: case IA64_BR0_REGNUM + 5: unw_access_br(info, regnum - IA64_BR0_REGNUM, ®, 1); break; } else if (regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127)) switch (regnum) { case IA64_FR0_REGNUM + 6: case IA64_FR0_REGNUM + 7: case IA64_FR0_REGNUM + 8: case IA64_FR0_REGNUM + 9: case IA64_FR0_REGNUM + 10: case IA64_FR0_REGNUM + 11: case IA64_FR0_REGNUM + 12: freg.u.bits[0] = reg; kgdb_hex2long(&ptr, &freg.u.bits[1]); *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) = freg; break; default: break; } else if (regnum == IA64_IP_REGNUM) ptregs->cr_iip = reg; else if (regnum == IA64_CFM_REGNUM) ptregs->cr_ifs = reg; else if (regnum == IA64_PSR_REGNUM) ptregs->cr_ipsr = reg; else if (regnum == IA64_PR_REGNUM) ptregs->pr = reg; else if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM) switch (regnum) { case IA64_CSD_REGNUM: ptregs->ar_csd = reg; break; case IA64_SSD_REGNUM: ptregs->ar_ssd = reg; case IA64_UNAT_REGNUM: ptregs->ar_unat = reg; case IA64_RNAT_REGNUM: unw_access_ar(info, UNW_AR_RNAT, ®, 1); break; case IA64_BSPSTORE_REGNUM: unw_access_ar(info, UNW_AR_BSPSTORE, ®, 1); break; case IA64_PFS_REGNUM: unw_access_ar(info, UNW_AR_PFS, ®, 1); break; case IA64_LC_REGNUM: unw_access_ar(info, UNW_AR_LC, ®, 1); break; case IA64_EC_REGNUM: unw_access_ar(info, UNW_AR_EC, ®, 1); break; case IA64_FPSR_REGNUM: ptregs->ar_fpsr = reg; break; case IA64_RSC_REGNUM: ptregs->ar_rsc = reg; break; case IA64_CCV_REGNUM: unw_access_ar(info, UNW_AR_CCV, ®, 1); break; } else strcpy(outbuffer, "E01"); return; }