|
@@ -49,55 +49,94 @@
|
|
|
#include <asm/system.h>
|
|
|
#include <asm/apic.h>
|
|
|
|
|
|
-/**
|
|
|
- * pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
|
|
|
- * @gdb_regs: A pointer to hold the registers in the order GDB wants.
|
|
|
- * @regs: The &struct pt_regs of the current process.
|
|
|
- *
|
|
|
- * Convert the pt_regs in @regs into the format for registers that
|
|
|
- * GDB expects, stored in @gdb_regs.
|
|
|
- */
|
|
|
-void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
|
|
|
{
|
|
|
-#ifndef CONFIG_X86_32
|
|
|
- u32 *gdb_regs32 = (u32 *)gdb_regs;
|
|
|
+#ifdef CONFIG_X86_32
|
|
|
+ { "ax", 4, offsetof(struct pt_regs, ax) },
|
|
|
+ { "cx", 4, offsetof(struct pt_regs, cx) },
|
|
|
+ { "dx", 4, offsetof(struct pt_regs, dx) },
|
|
|
+ { "bx", 4, offsetof(struct pt_regs, bx) },
|
|
|
+ { "sp", 4, offsetof(struct pt_regs, sp) },
|
|
|
+ { "bp", 4, offsetof(struct pt_regs, bp) },
|
|
|
+ { "si", 4, offsetof(struct pt_regs, si) },
|
|
|
+ { "di", 4, offsetof(struct pt_regs, di) },
|
|
|
+ { "ip", 4, offsetof(struct pt_regs, ip) },
|
|
|
+ { "flags", 4, offsetof(struct pt_regs, flags) },
|
|
|
+ { "cs", 4, offsetof(struct pt_regs, cs) },
|
|
|
+ { "ss", 4, offsetof(struct pt_regs, ss) },
|
|
|
+ { "ds", 4, offsetof(struct pt_regs, ds) },
|
|
|
+ { "es", 4, offsetof(struct pt_regs, es) },
|
|
|
+ { "fs", 4, -1 },
|
|
|
+ { "gs", 4, -1 },
|
|
|
+#else
|
|
|
+ { "ax", 8, offsetof(struct pt_regs, ax) },
|
|
|
+ { "bx", 8, offsetof(struct pt_regs, bx) },
|
|
|
+ { "cx", 8, offsetof(struct pt_regs, cx) },
|
|
|
+ { "dx", 8, offsetof(struct pt_regs, dx) },
|
|
|
+ { "si", 8, offsetof(struct pt_regs, dx) },
|
|
|
+ { "di", 8, offsetof(struct pt_regs, di) },
|
|
|
+ { "bp", 8, offsetof(struct pt_regs, bp) },
|
|
|
+ { "sp", 8, offsetof(struct pt_regs, sp) },
|
|
|
+ { "r8", 8, offsetof(struct pt_regs, r8) },
|
|
|
+ { "r9", 8, offsetof(struct pt_regs, r9) },
|
|
|
+ { "r10", 8, offsetof(struct pt_regs, r10) },
|
|
|
+ { "r11", 8, offsetof(struct pt_regs, r11) },
|
|
|
+ { "r12", 8, offsetof(struct pt_regs, r12) },
|
|
|
+ { "r13", 8, offsetof(struct pt_regs, r13) },
|
|
|
+ { "r14", 8, offsetof(struct pt_regs, r14) },
|
|
|
+ { "r15", 8, offsetof(struct pt_regs, r15) },
|
|
|
+ { "ip", 8, offsetof(struct pt_regs, ip) },
|
|
|
+ { "flags", 4, offsetof(struct pt_regs, flags) },
|
|
|
+ { "cs", 4, offsetof(struct pt_regs, cs) },
|
|
|
+ { "ss", 4, offsetof(struct pt_regs, ss) },
|
|
|
#endif
|
|
|
- gdb_regs[GDB_AX] = regs->ax;
|
|
|
- gdb_regs[GDB_BX] = regs->bx;
|
|
|
- gdb_regs[GDB_CX] = regs->cx;
|
|
|
- gdb_regs[GDB_DX] = regs->dx;
|
|
|
- gdb_regs[GDB_SI] = regs->si;
|
|
|
- gdb_regs[GDB_DI] = regs->di;
|
|
|
- gdb_regs[GDB_BP] = regs->bp;
|
|
|
- gdb_regs[GDB_PC] = regs->ip;
|
|
|
+};
|
|
|
+
|
|
|
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
|
|
|
+{
|
|
|
+ if (
|
|
|
#ifdef CONFIG_X86_32
|
|
|
- gdb_regs[GDB_PS] = regs->flags;
|
|
|
- gdb_regs[GDB_DS] = regs->ds;
|
|
|
- gdb_regs[GDB_ES] = regs->es;
|
|
|
- gdb_regs[GDB_CS] = regs->cs;
|
|
|
- gdb_regs[GDB_FS] = 0xFFFF;
|
|
|
- gdb_regs[GDB_GS] = 0xFFFF;
|
|
|
- if (user_mode_vm(regs)) {
|
|
|
- gdb_regs[GDB_SS] = regs->ss;
|
|
|
- gdb_regs[GDB_SP] = regs->sp;
|
|
|
- } else {
|
|
|
- gdb_regs[GDB_SS] = __KERNEL_DS;
|
|
|
- gdb_regs[GDB_SP] = kernel_stack_pointer(regs);
|
|
|
+ regno == GDB_SS || regno == GDB_FS || regno == GDB_GS ||
|
|
|
+#endif
|
|
|
+ regno == GDB_SP || regno == GDB_ORIG_AX)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (dbg_reg_def[regno].offset != -1)
|
|
|
+ memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
|
|
|
+ dbg_reg_def[regno].size);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
|
|
|
+{
|
|
|
+ if (regno == GDB_ORIG_AX) {
|
|
|
+ memcpy(mem, ®s->orig_ax, sizeof(regs->orig_ax));
|
|
|
+ return "orig_ax";
|
|
|
}
|
|
|
-#else
|
|
|
- gdb_regs[GDB_R8] = regs->r8;
|
|
|
- gdb_regs[GDB_R9] = regs->r9;
|
|
|
- gdb_regs[GDB_R10] = regs->r10;
|
|
|
- gdb_regs[GDB_R11] = regs->r11;
|
|
|
- gdb_regs[GDB_R12] = regs->r12;
|
|
|
- gdb_regs[GDB_R13] = regs->r13;
|
|
|
- gdb_regs[GDB_R14] = regs->r14;
|
|
|
- gdb_regs[GDB_R15] = regs->r15;
|
|
|
- gdb_regs32[GDB_PS] = regs->flags;
|
|
|
- gdb_regs32[GDB_CS] = regs->cs;
|
|
|
- gdb_regs32[GDB_SS] = regs->ss;
|
|
|
- gdb_regs[GDB_SP] = kernel_stack_pointer(regs);
|
|
|
+ if (regno >= DBG_MAX_REG_NUM || regno < 0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (dbg_reg_def[regno].offset != -1)
|
|
|
+ memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
|
|
|
+ dbg_reg_def[regno].size);
|
|
|
+
|
|
|
+ switch (regno) {
|
|
|
+#ifdef CONFIG_X86_32
|
|
|
+ case GDB_SS:
|
|
|
+ if (!user_mode_vm(regs))
|
|
|
+ *(unsigned long *)mem = __KERNEL_DS;
|
|
|
+ break;
|
|
|
+ case GDB_SP:
|
|
|
+ if (!user_mode_vm(regs))
|
|
|
+ *(unsigned long *)mem = kernel_stack_pointer(regs);
|
|
|
+ break;
|
|
|
+ case GDB_GS:
|
|
|
+ case GDB_FS:
|
|
|
+ *(unsigned long *)mem = 0xFFFF;
|
|
|
+ break;
|
|
|
#endif
|
|
|
+ }
|
|
|
+ return dbg_reg_def[regno].name;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -150,47 +189,6 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
|
|
gdb_regs[GDB_SP] = p->thread.sp;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs.
|
|
|
- * @gdb_regs: A pointer to hold the registers we've received from GDB.
|
|
|
- * @regs: A pointer to a &struct pt_regs to hold these values in.
|
|
|
- *
|
|
|
- * Convert the GDB regs in @gdb_regs into the pt_regs, and store them
|
|
|
- * in @regs.
|
|
|
- */
|
|
|
-void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
-{
|
|
|
-#ifndef CONFIG_X86_32
|
|
|
- u32 *gdb_regs32 = (u32 *)gdb_regs;
|
|
|
-#endif
|
|
|
- regs->ax = gdb_regs[GDB_AX];
|
|
|
- regs->bx = gdb_regs[GDB_BX];
|
|
|
- regs->cx = gdb_regs[GDB_CX];
|
|
|
- regs->dx = gdb_regs[GDB_DX];
|
|
|
- regs->si = gdb_regs[GDB_SI];
|
|
|
- regs->di = gdb_regs[GDB_DI];
|
|
|
- regs->bp = gdb_regs[GDB_BP];
|
|
|
- regs->ip = gdb_regs[GDB_PC];
|
|
|
-#ifdef CONFIG_X86_32
|
|
|
- regs->flags = gdb_regs[GDB_PS];
|
|
|
- regs->ds = gdb_regs[GDB_DS];
|
|
|
- regs->es = gdb_regs[GDB_ES];
|
|
|
- regs->cs = gdb_regs[GDB_CS];
|
|
|
-#else
|
|
|
- regs->r8 = gdb_regs[GDB_R8];
|
|
|
- regs->r9 = gdb_regs[GDB_R9];
|
|
|
- regs->r10 = gdb_regs[GDB_R10];
|
|
|
- regs->r11 = gdb_regs[GDB_R11];
|
|
|
- regs->r12 = gdb_regs[GDB_R12];
|
|
|
- regs->r13 = gdb_regs[GDB_R13];
|
|
|
- regs->r14 = gdb_regs[GDB_R14];
|
|
|
- regs->r15 = gdb_regs[GDB_R15];
|
|
|
- regs->flags = gdb_regs32[GDB_PS];
|
|
|
- regs->cs = gdb_regs32[GDB_CS];
|
|
|
- regs->ss = gdb_regs32[GDB_SS];
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
static struct hw_breakpoint {
|
|
|
unsigned enabled;
|
|
|
unsigned long addr;
|