📄 gdbstub.c
字号:
reg, &nat, rw); return result;}static int kgdb_br_reg(int regnum, struct pt_regs * ptregs, struct unw_frame_info *info, unsigned long *reg, int rw){ int i, result = 1; if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7))) return 0; switch (regnum) { case IA64_BR0_REGNUM: case IA64_BR0_REGNUM + 6: case IA64_BR0_REGNUM + 7: if (rw) { for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) if (br_reg_to_ptreg_index[i].reg == regnum) { *((unsigned long *) (((void *)ptregs) + br_reg_to_ptreg_index[i].ptregoff)) = *reg; break; } } else for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) if (br_reg_to_ptreg_index[i].reg == regnum) { *reg = *((unsigned long *) (((void *)ptregs) + br_reg_to_ptreg_index[i]. ptregoff)); 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: result = !unw_access_br(info, regnum - IA64_BR0_REGNUM, reg, rw); break; } return result;}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;}static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs, struct unw_frame_info *info, unsigned long *reg, int rw){ int result = 0, i; if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM)) return 0; if (rw && ptregs) { for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) if (ar_reg_to_ptreg_index[i].reg == regnum) { *((unsigned long *) (((void *)ptregs) + ar_reg_to_ptreg_index[i].ptregoff)) = *reg; result = 1; break; } } else if (ptregs) { for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) if (ar_reg_to_ptreg_index[i].reg == regnum) { *reg = *((unsigned long *) (((void *)ptregs) + ar_reg_to_ptreg_index[i].ptregoff)); result = 1; break; } } if (result) return result; result = 1; switch (regnum) { case IA64_CSD_REGNUM: result = !unw_access_ar(info, UNW_AR_CSD, reg, rw); break; case IA64_SSD_REGNUM: result = !unw_access_ar(info, UNW_AR_SSD, reg, rw); break; case IA64_UNAT_REGNUM: result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); break; case IA64_RNAT_REGNUM: result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); break; case IA64_BSPSTORE_REGNUM: result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); break; case IA64_PFS_REGNUM: result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); break; case IA64_LC_REGNUM: result = !unw_access_ar(info, UNW_AR_LC, reg, rw); break; case IA64_EC_REGNUM: result = !unw_access_ar(info, UNW_AR_EC, reg, rw); break; case IA64_FPSR_REGNUM: result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw); break; case IA64_RSC_REGNUM: result = !unw_access_ar(info, UNW_AR_RSC, reg, rw); break; case IA64_CCV_REGNUM: result = !unw_access_ar(info, UNW_AR_CCV, reg, rw); break; default: result = 0; } return result;}#ifndef XENvoid kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info, struct pt_regs *ptregs)#elsestatic intkgdb_get_reg(int regnum, struct unw_frame_info *info, struct cpu_user_regs* ptregs, unsigned long* __reg, struct ia64_fpreg* __freg)#endif{ unsigned long reg, size = 0, *mem = ® struct ia64_fpreg freg; if (kgdb_gr_reg(regnum, info, ®, 0) || kgdb_gr_ptreg(regnum, ptregs, info, ®, 0) || kgdb_br_reg(regnum, ptregs, info, ®, 0) || kgdb_ar_reg(regnum, ptregs, info, ®, 0)) size = sizeof(reg); else if (kgdb_fr_reg(regnum, NULL, ptregs, info, ®, &freg, 0)) { size = sizeof(freg); mem = (unsigned long *)&freg; } else if (regnum == IA64_IP_REGNUM) { if (!ptregs) { unw_get_ip(info, ®); size = sizeof(reg); } else { reg = ptregs->cr_iip; size = sizeof(reg); } } else if (regnum == IA64_CFM_REGNUM) { if (!ptregs) unw_get_cfm(info, ®); else reg = ptregs->cr_ifs; size = sizeof(reg); } else if (regnum == IA64_PSR_REGNUM) {#ifndef XEN if (!ptregs && kgdb_usethread) ptregs = (struct pt_regs *) ((unsigned long)kgdb_usethread + IA64_STK_OFFSET) - 1;#endif if (ptregs) reg = ptregs->cr_ipsr; size = sizeof(reg); } else if (regnum == IA64_PR_REGNUM) { if (ptregs) reg = ptregs->pr; else unw_access_pr(info, ®, 0); size = sizeof(reg); } else if (regnum == IA64_BSP_REGNUM) { unw_get_bsp(info, ®); size = sizeof(reg); }#ifndef XEN if (size) { kgdb_mem2hex((char *) mem, outbuffer, size); outbuffer[size*2] = 0; } else strlcpy(outbuffer, "E0", sizeof("E0")); return;#else if (size) { if (size == sizeof(reg)) { *__reg = reg; } else { BUG_ON(size != sizeof(freg)); *__freg = freg; } return 0; } return -1;#endif}#ifndef XENstatic int inline kgdb_get_blocked_state(struct task_struct *p, struct unw_frame_info *unw)#elsestatic intkgdb_get_blocked_state(struct vcpu *p, struct cpu_user_regs *regs, struct unw_frame_info *unw)#endif{ unsigned long ip; int count = 0;#ifndef XEN unw_init_from_blocked_task(unw, p);#endif ip = 0UL; do { if (unw_unwind(unw) < 0) return -1; unw_get_ip(unw, &ip);#ifndef XEN if (!in_sched_functions(ip)) break;#else dbg_printk("ip 0x%lx cr_iip 0x%lx\n", ip, regs->cr_iip); if (ip == regs->cr_iip) break;#endif } while (count++ < 16); if (!ip) return -1; else return 0;}struct gdb_callback_arg{ struct cpu_user_regs* regs; unsigned long regnum; unsigned long* reg; struct pt_fpreg* freg; int error; // 1: not supported // 0: success // -1: failure};static voidgdb_get_reg_callback(struct unw_frame_info* info, void* __arg){ struct gdb_callback_arg* arg = (struct gdb_callback_arg*)__arg; if (kgdb_get_blocked_state(current, arg->regs, info) < 0) { dbg_printk("%s: kgdb_get_blocked_state failed\n", __func__); arg->error = -1; return; } //XXX struct ia64_fpreg and struct pt_fpreg are same. if (kgdb_get_reg(arg->regnum, info, arg->regs, arg->reg, (struct ia64_fpreg*)arg->freg) < 0) { dbg_printk("%s: kgdb_get_reg failed\n", __func__); arg->error = 1; return; } arg->error = 0; return;}void gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs, struct gdb_context *ctx){ struct gdb_callback_arg arg; unsigned long reg; struct pt_fpreg freg; char buf[16 * 2 + 1]; if (regnum >= NUM_REGS) { dbg_printk("%s: regnum %ld\n", __func__, regnum); goto out_err; } arg.regs = regs; arg.regnum = regnum; arg.reg = ® arg.freg = &freg; arg.error = 0; unw_init_running(&gdb_get_reg_callback, (void*)&arg); if (arg.error < 0) { dbg_printk("%s: gdb_get_reg_callback failed\n", __func__); goto out_err; } if (arg.error > 0) { // notify gdb that this register is not supported. // see fetch_register_using_p() in gdb/remote.c. safe_strcpy(buf, "x"); } else if (IA64_FR0_REGNUM <= regnum && regnum <= IA64_FR0_REGNUM + 127) { snprintf(buf, sizeof(buf), "%.016lx", swab64(freg.u.bits[0])); snprintf(buf + 16, sizeof(buf) - 16, "%.016lx", swab64(freg.u.bits[1])); } else { snprintf(buf, sizeof(buf), "%.016lx", swab64(reg)); }out: return gdb_send_reply(buf, ctx);out_err: dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum); safe_strcpy(buf, "E0"); goto out;}#endifvoid gdb_arch_resume(struct cpu_user_regs *regs, unsigned long addr, unsigned long type, struct gdb_context *ctx){ /* XXX */ if (type == GDB_STEP) { gdb_send_reply("S01", ctx); }}voidgdb_arch_print_state(struct cpu_user_regs *regs){ /* XXX */}voidgdb_arch_enter(struct cpu_user_regs *regs){ /* nothing */}voidgdb_arch_exit(struct cpu_user_regs *regs){ /* nothing */}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -