📄 gdbstub.c
字号:
/* * ia64-specific cdb routines * cdb xen/ia64 by Isaku Yamahta <yamahata at valinux co jp> * VA Linux Systems Japan K.K. * some routines are stolen from kgdb/ia64. *//* * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * *//* * Copyright (C) 2000-2001 VERITAS Software Corporation. *//* * Contributor: Lake Stevens Instrument Division$ * Written by: Glenn Engel $ * Updated by: Amit Kale<akale@veritas.com> * Modified for 386 by Jim Kingdon, Cygnus Support. * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com> * */#include <xen/lib.h>#include <xen/mm.h>#include <asm/byteorder.h>#include <asm/debugger.h>#include <asm/uaccess.h>#define USE_UNWIND#ifdef USE_UNWIND#include <asm/unwind.h>#endif/* Printk isn't particularly safe just after we've trapped to the debugger. so avoid it. */#define dbg_printk(...)//#define dbg_printk(...) printk(__VA_ARGS__)u16gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie){ /* XXX */ return 1;}void gdb_arch_read_reg_array(struct cpu_user_regs *regs, struct gdb_context *ctx){ gdb_send_reply("", ctx);}void gdb_arch_write_reg(unsigned long regnum, unsigned long val, struct cpu_user_regs *regs, struct gdb_context *ctx){ gdb_send_reply("", ctx);} void gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char* buf, struct gdb_context *ctx){ /* XXX TODO */ gdb_send_reply("E02", ctx);}/* Like copy_from_user, but safe to call with interrupts disabled. Trust me, and don't look behind the curtain. */unsignedgdb_arch_copy_from_user(void *dest, const void *src, unsigned len){ int val; __asm__ __volatile__( "cmp4.eq p6, p0 = r0, %1\n" "(p6) br.cond.dptk 2f\n" "[1:]\n" ".xdata4 \"__ex_table\", 99f-., 2f-.;\n" "[99:] ld1 %0 = [%3], 1\n" ";;\n" ".xdata4 \"__ex_table\", 99f-., 2f-.;\n" "[99:] st1 [%2] = %0, 1\n" "adds %1 = -1, %1\n" ";;\n" "cmp4.eq p0, p6 = r0, %1\n" "(p6) br.cond.dptk 1b\n" "[2:]\n" : "=r"(val), "=r"(len), "=r"(dest), "=r"(src) : "1"(len), "2"(dest), "3"(src) : "memory", "p6"); return len;}unsigned int gdb_arch_copy_to_user(void *dest, const void *src, unsigned len){ /* XXX */ return len;}#define NUM_REGS 590#define REGISTER_BYTES (NUM_REGS*8+128*8)#define REGISTER_BYTE(N) (((N) * 8) \ + ((N) <= IA64_FR0_REGNUM ? \ 0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM)))#define REGISTER_SIZE(N) \ (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8)#define IA64_GR0_REGNUM 0#define IA64_FR0_REGNUM 128#define IA64_FR127_REGNUM (IA64_FR0_REGNUM+127)#define IA64_PR0_REGNUM 256#define IA64_BR0_REGNUM 320#define IA64_VFP_REGNUM 328#define IA64_PR_REGNUM 330#define IA64_IP_REGNUM 331#define IA64_PSR_REGNUM 332#define IA64_CFM_REGNUM 333#define IA64_AR0_REGNUM 334#define IA64_NAT0_REGNUM 462#define IA64_NAT31_REGNUM (IA64_NAT0_REGNUM+31)#define IA64_NAT32_REGNUM (IA64_NAT0_REGNUM+32)#define IA64_RSC_REGNUM (IA64_AR0_REGNUM+16)#define IA64_BSP_REGNUM (IA64_AR0_REGNUM+17)#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM+18)#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM+19)#define IA64_FCR_REGNUM (IA64_AR0_REGNUM+21)#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM+24)#define IA64_CSD_REGNUM (IA64_AR0_REGNUM+25)#define IA64_SSD_REGNUM (IA64_AR0_REGNUM+26)#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM+27)#define IA64_FSR_REGNUM (IA64_AR0_REGNUM+28)#define IA64_FIR_REGNUM (IA64_AR0_REGNUM+29)#define IA64_FDR_REGNUM (IA64_AR0_REGNUM+30)#define IA64_CCV_REGNUM (IA64_AR0_REGNUM+32)#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM+36)#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM+40)#define IA64_ITC_REGNUM (IA64_AR0_REGNUM+44)#define IA64_PFS_REGNUM (IA64_AR0_REGNUM+64)#define IA64_LC_REGNUM (IA64_AR0_REGNUM+65)#define IA64_EC_REGNUM (IA64_AR0_REGNUM+66)#ifndef USE_UNWINDstruct regs_to_cpu_user_resgs_index { unsigned int reg; unsigned int ptregoff;};#define ptoff(V) ((unsigned int)&((struct cpu_user_regs*)0x0)->V)// grstatic const struct regs_to_cpu_user_resgs_indexgr_reg_to_cpu_user_regs_index[] = { {IA64_GR0_REGNUM + 8, ptoff(r8)}, {IA64_GR0_REGNUM + 9, ptoff(r9)}, {IA64_GR0_REGNUM + 10, ptoff(r10)}, {IA64_GR0_REGNUM + 11, ptoff(r11)}, {IA64_GR0_REGNUM + 1, ptoff(r1)}, {IA64_GR0_REGNUM + 12, ptoff(r12)}, {IA64_GR0_REGNUM + 13, ptoff(r13)}, {IA64_GR0_REGNUM + 15, ptoff(r15)}, {IA64_GR0_REGNUM + 14, ptoff(r14)}, {IA64_GR0_REGNUM + 2, ptoff(r2)}, {IA64_GR0_REGNUM + 3, ptoff(r3)}, {IA64_GR0_REGNUM + 16, ptoff(r16)}, {IA64_GR0_REGNUM + 17, ptoff(r17)}, {IA64_GR0_REGNUM + 18, ptoff(r18)}, {IA64_GR0_REGNUM + 19, ptoff(r19)}, {IA64_GR0_REGNUM + 20, ptoff(r20)}, {IA64_GR0_REGNUM + 21, ptoff(r21)}, {IA64_GR0_REGNUM + 22, ptoff(r22)}, {IA64_GR0_REGNUM + 23, ptoff(r23)}, {IA64_GR0_REGNUM + 24, ptoff(r24)}, {IA64_GR0_REGNUM + 25, ptoff(r25)}, {IA64_GR0_REGNUM + 26, ptoff(r26)}, {IA64_GR0_REGNUM + 27, ptoff(r27)}, {IA64_GR0_REGNUM + 28, ptoff(r28)}, {IA64_GR0_REGNUM + 29, ptoff(r29)}, {IA64_GR0_REGNUM + 30, ptoff(r30)}, {IA64_GR0_REGNUM + 31, ptoff(r31)}, {IA64_GR0_REGNUM + 4, ptoff(r4)}, {IA64_GR0_REGNUM + 5, ptoff(r5)}, {IA64_GR0_REGNUM + 6, ptoff(r6)}, {IA64_GR0_REGNUM + 7, ptoff(r7)},};static const int gr_reg_to_cpu_user_regs_index_max = sizeof(gr_reg_to_cpu_user_regs_index) / sizeof(gr_reg_to_cpu_user_regs_index[0]); // brstatic const struct regs_to_cpu_user_resgs_indexbr_reg_to_cpu_user_regs_index[] = { {IA64_BR0_REGNUM + 0, ptoff(b0)}, {IA64_BR0_REGNUM + 6, ptoff(b6)}, {IA64_BR0_REGNUM + 7, ptoff(b7)},};static const int br_reg_to_cpu_user_regs_index_max = sizeof(br_reg_to_cpu_user_regs_index) / sizeof(br_reg_to_cpu_user_regs_index[0]); // fstatic const struct regs_to_cpu_user_resgs_indexfr_reg_to_cpu_user_regs_index[] = { {IA64_FR0_REGNUM + 6, ptoff(f6)}, {IA64_FR0_REGNUM + 7, ptoff(f7)}, {IA64_FR0_REGNUM + 8, ptoff(f8)}, {IA64_FR0_REGNUM + 9, ptoff(f9)}, {IA64_FR0_REGNUM + 10, ptoff(f10)}, {IA64_FR0_REGNUM + 11, ptoff(f11)},};static const int fr_reg_to_cpu_user_regs_index_max = sizeof(fr_reg_to_cpu_user_regs_index) / sizeof(fr_reg_to_cpu_user_regs_index[0]); void gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs, struct gdb_context *ctx){ unsigned long reg = IA64_IP_REGNUM; char buf[9]; int i; dbg_printk("Register read regnum = 0x%lx\n", regnum); if (IA64_GR0_REGNUM <= regnum && regnum <= IA64_GR0_REGNUM + 31) { for (i = 0; i < gr_reg_to_cpu_user_regs_index_max; i++) { if (gr_reg_to_cpu_user_regs_index[i].reg == regnum) { reg = *(unsigned long*)(((char*)regs) + gr_reg_to_cpu_user_regs_index[i].ptregoff); break; } } if (i == gr_reg_to_cpu_user_regs_index_max) { goto out_err; } } else if (IA64_BR0_REGNUM <= regnum && regnum <= IA64_BR0_REGNUM + 7) { for (i = 0; i < br_reg_to_cpu_user_regs_index_max; i++) { if (br_reg_to_cpu_user_regs_index[i].reg == regnum) { reg = *(unsigned long*)(((char*)regs) + br_reg_to_cpu_user_regs_index[i].ptregoff); break; } } if (i == br_reg_to_cpu_user_regs_index_max) { goto out_err; } } else if (IA64_FR0_REGNUM + 6 <= regnum && regnum <= IA64_FR0_REGNUM + 11) { for (i = 0; i < fr_reg_to_cpu_user_regs_index_max; i++) { if (fr_reg_to_cpu_user_regs_index[i].reg == regnum) { reg = *(unsigned long*)(((char*)regs) + fr_reg_to_cpu_user_regs_index[i].ptregoff); break; } } if (i == fr_reg_to_cpu_user_regs_index_max) { goto out_err; } } else if (regnum == IA64_CSD_REGNUM) { reg = regs->ar_csd; } else if (regnum == IA64_SSD_REGNUM) { reg = regs->ar_ssd; } else if (regnum == IA64_PSR_REGNUM) { reg = regs->cr_ipsr; } else if (regnum == IA64_IP_REGNUM) { reg = regs->cr_iip; } else if (regnum == IA64_CFM_REGNUM) { reg = regs->cr_ifs; } else if (regnum == IA64_UNAT_REGNUM) { reg = regs->ar_unat; } else if (regnum == IA64_PFS_REGNUM) { reg = regs->ar_pfs; } else if (regnum == IA64_RSC_REGNUM) { reg = regs->ar_rsc; } else if (regnum == IA64_RNAT_REGNUM) { reg = regs->ar_rnat; } else if (regnum == IA64_BSPSTORE_REGNUM) { reg = regs->ar_bspstore; } else if (regnum == IA64_PR_REGNUM) { reg = regs->pr; } else if (regnum == IA64_FPSR_REGNUM) { reg = regs->ar_fpsr; } else if (regnum == IA64_CCV_REGNUM) { reg = regs->ar_ccv; } else { // emul_unat, rfi_pfs goto out_err; } dbg_printk("Register read regnum = 0x%lx, val = 0x%lx\n", regnum, reg); snprintf(buf, sizeof(buf), "%.08lx", swab64(reg));out: return gdb_send_reply(buf, ctx);out_err: dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum); safe_strcpy(buf, "x"); goto out;}#else#define ptoff(V) ((unsigned int) &((struct pt_regs *)0x0)->V)struct reg_to_ptreg_index { unsigned int reg; unsigned int ptregoff;};static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = { {IA64_GR0_REGNUM + 1, ptoff(r1)}, {IA64_GR0_REGNUM + 2, ptoff(r2)}, {IA64_GR0_REGNUM + 3, ptoff(r3)}, {IA64_GR0_REGNUM + 8, ptoff(r8)}, {IA64_GR0_REGNUM + 9, ptoff(r9)}, {IA64_GR0_REGNUM + 10, ptoff(r10)}, {IA64_GR0_REGNUM + 11, ptoff(r11)}, {IA64_GR0_REGNUM + 12, ptoff(r12)}, {IA64_GR0_REGNUM + 13, ptoff(r13)}, {IA64_GR0_REGNUM + 14, ptoff(r14)}, {IA64_GR0_REGNUM + 15, ptoff(r15)}, {IA64_GR0_REGNUM + 16, ptoff(r16)}, {IA64_GR0_REGNUM + 17, ptoff(r17)}, {IA64_GR0_REGNUM + 18, ptoff(r18)}, {IA64_GR0_REGNUM + 19, ptoff(r19)}, {IA64_GR0_REGNUM + 20, ptoff(r20)}, {IA64_GR0_REGNUM + 21, ptoff(r21)}, {IA64_GR0_REGNUM + 22, ptoff(r22)}, {IA64_GR0_REGNUM + 23, ptoff(r23)}, {IA64_GR0_REGNUM + 24, ptoff(r24)}, {IA64_GR0_REGNUM + 25, ptoff(r25)}, {IA64_GR0_REGNUM + 26, ptoff(r26)}, {IA64_GR0_REGNUM + 27, ptoff(r27)}, {IA64_GR0_REGNUM + 28, ptoff(r28)}, {IA64_GR0_REGNUM + 29, ptoff(r29)}, {IA64_GR0_REGNUM + 30, ptoff(r30)}, {IA64_GR0_REGNUM + 31, ptoff(r31)},};static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = { {IA64_BR0_REGNUM, ptoff(b0)}, {IA64_BR0_REGNUM + 6, ptoff(b6)}, {IA64_BR0_REGNUM + 7, ptoff(b7)},};static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = { {IA64_PFS_REGNUM, ptoff(ar_pfs)}, {IA64_UNAT_REGNUM, ptoff(ar_unat)}, {IA64_RNAT_REGNUM, ptoff(ar_rnat)}, {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)}, {IA64_RSC_REGNUM, ptoff(ar_rsc)}, {IA64_CSD_REGNUM, ptoff(ar_csd)}, {IA64_SSD_REGNUM, ptoff(ar_ssd)}, {IA64_FPSR_REGNUM, ptoff(ar_fpsr)}, {IA64_CCV_REGNUM, ptoff(ar_ccv)},};#ifndef XENextern atomic_t cpu_doing_single_step;#endifstatic int kgdb_gr_reg(int regnum, struct unw_frame_info *info, unsigned long *reg, int rw){ char nat; if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) || (regnum >= (IA64_GR0_REGNUM + 4) && regnum <= (IA64_GR0_REGNUM + 7))) return !unw_access_gr(info, regnum - IA64_GR0_REGNUM, reg, &nat, rw); else return 0;}static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs, struct unw_frame_info *info, unsigned long *reg, int rw){ int i, result = 1; char nat; if (!((regnum >= (IA64_GR0_REGNUM + 2) && regnum <= (IA64_GR0_REGNUM + 3)) || (regnum >= (IA64_GR0_REGNUM + 8) && regnum <= (IA64_GR0_REGNUM + 15)) || (regnum >= (IA64_GR0_REGNUM + 16) && regnum <= (IA64_GR0_REGNUM + 31)))) return 0; else if (rw && ptregs) { for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) if (gr_reg_to_ptreg_index[i].reg == regnum) { *((unsigned long *)(((void *)ptregs) + gr_reg_to_ptreg_index[i].ptregoff)) = *reg; break; } } else if (!rw && ptregs) { for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) if (gr_reg_to_ptreg_index[i].reg == regnum) { *reg = *((unsigned long *) (((void *)ptregs) + gr_reg_to_ptreg_index[i].ptregoff)); break; } } else result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -