|
@@ -69,6 +69,9 @@ static int gdb_x86vector = -1;
|
|
|
*/
|
|
|
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
{
|
|
|
+#ifndef CONFIG_X86_32
|
|
|
+ u32 *gdb_regs32 = (u32 *)gdb_regs;
|
|
|
+#endif
|
|
|
gdb_regs[GDB_AX] = regs->ax;
|
|
|
gdb_regs[GDB_BX] = regs->bx;
|
|
|
gdb_regs[GDB_CX] = regs->cx;
|
|
@@ -76,9 +79,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
gdb_regs[GDB_SI] = regs->si;
|
|
|
gdb_regs[GDB_DI] = regs->di;
|
|
|
gdb_regs[GDB_BP] = regs->bp;
|
|
|
- gdb_regs[GDB_PS] = regs->flags;
|
|
|
gdb_regs[GDB_PC] = regs->ip;
|
|
|
#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;
|
|
@@ -94,6 +97,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
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;
|
|
|
#endif
|
|
|
gdb_regs[GDB_SP] = regs->sp;
|
|
|
}
|
|
@@ -112,6 +118,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
*/
|
|
|
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
|
|
{
|
|
|
+#ifndef CONFIG_X86_32
|
|
|
+ u32 *gdb_regs32 = (u32 *)gdb_regs;
|
|
|
+#endif
|
|
|
gdb_regs[GDB_AX] = 0;
|
|
|
gdb_regs[GDB_BX] = 0;
|
|
|
gdb_regs[GDB_CX] = 0;
|
|
@@ -129,8 +138,10 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
|
|
gdb_regs[GDB_FS] = 0xFFFF;
|
|
|
gdb_regs[GDB_GS] = 0xFFFF;
|
|
|
#else
|
|
|
- gdb_regs[GDB_PS] = *(unsigned long *)(p->thread.sp + 8);
|
|
|
- gdb_regs[GDB_PC] = 0;
|
|
|
+ gdb_regs32[GDB_PS] = *(unsigned long *)(p->thread.sp + 8);
|
|
|
+ gdb_regs32[GDB_CS] = __KERNEL_CS;
|
|
|
+ gdb_regs32[GDB_SS] = __KERNEL_DS;
|
|
|
+ gdb_regs[GDB_PC] = p->thread.ip;
|
|
|
gdb_regs[GDB_R8] = 0;
|
|
|
gdb_regs[GDB_R9] = 0;
|
|
|
gdb_regs[GDB_R10] = 0;
|
|
@@ -153,6 +164,9 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
|
|
*/
|
|
|
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];
|
|
@@ -160,9 +174,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
regs->si = gdb_regs[GDB_SI];
|
|
|
regs->di = gdb_regs[GDB_DI];
|
|
|
regs->bp = gdb_regs[GDB_BP];
|
|
|
- regs->flags = gdb_regs[GDB_PS];
|
|
|
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];
|
|
@@ -175,6 +189,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
|
|
|
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
|
|
|
}
|
|
|
|
|
@@ -378,10 +395,8 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
|
|
|
if (remcomInBuffer[0] == 's') {
|
|
|
linux_regs->flags |= X86_EFLAGS_TF;
|
|
|
kgdb_single_step = 1;
|
|
|
- if (kgdb_contthread) {
|
|
|
- atomic_set(&kgdb_cpu_doing_single_step,
|
|
|
- raw_smp_processor_id());
|
|
|
- }
|
|
|
+ atomic_set(&kgdb_cpu_doing_single_step,
|
|
|
+ raw_smp_processor_id());
|
|
|
}
|
|
|
|
|
|
get_debugreg(dr6, 6);
|
|
@@ -466,9 +481,15 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
|
|
|
|
|
|
case DIE_DEBUG:
|
|
|
if (atomic_read(&kgdb_cpu_doing_single_step) ==
|
|
|
- raw_smp_processor_id() &&
|
|
|
- user_mode(regs))
|
|
|
- return single_step_cont(regs, args);
|
|
|
+ raw_smp_processor_id()) {
|
|
|
+ if (user_mode(regs))
|
|
|
+ return single_step_cont(regs, args);
|
|
|
+ break;
|
|
|
+ } else if (test_thread_flag(TIF_SINGLESTEP))
|
|
|
+ /* This means a user thread is single stepping
|
|
|
+ * a system call which should be ignored
|
|
|
+ */
|
|
|
+ return NOTIFY_DONE;
|
|
|
/* fall through */
|
|
|
default:
|
|
|
if (user_mode(regs))
|