Dumping registers from other sleeping tasks in KGDB was totally
failing for me.  All registers were reported as 0.

It looks as if the code was looking at at "task_pt_regs(task)" for the
sleeping task and they were all 0.  I'm not exactly sure why this
structure was used and why it wasn't filled in.

There is a more reliable place to look for all of the important
registers for a sleeping task: the task_thread_info.  This is the same
place that is referred to when doing a dump of all sleeping task
stacks (kdb_show_stack() -> show_stack() -> dump_backtrace() ->
unwind_backtrace() -> thread_saved_sp()).

Let's use the more reliable place for all registers that are saved
there.  We'll fall back to the task_pt_regs() for registers that we
don't have.

Signed-off-by: Doug Anderson <[email protected]>
---
 arch/arm/kernel/kgdb.c | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
index 07db2f8..bab69db 100644
--- a/arch/arm/kernel/kgdb.c
+++ b/arch/arm/kernel/kgdb.c
@@ -75,6 +75,7 @@ int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
 void
 sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
 {
+       struct thread_info *ti;
        struct pt_regs *thread_regs;
        int regno;
 
@@ -86,24 +87,34 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct 
task_struct *task)
        for (regno = 0; regno < GDB_MAX_REGS; regno++)
                gdb_regs[regno] = 0;
 
-       /* Otherwise, we have only some registers from switch_to() */
+       /*
+        * Try to get as much as we can from the thread_info since the
+        * pt_regs structure doesn't seem right in most cases.
+        */
+       ti                      = task_thread_info(task);
+       gdb_regs[_R4]           = ti->cpu_context.r4;
+       gdb_regs[_R5]           = ti->cpu_context.r5;
+       gdb_regs[_R6]           = ti->cpu_context.r6;
+       gdb_regs[_R7]           = ti->cpu_context.r7;
+       gdb_regs[_R8]           = ti->cpu_context.r8;
+       gdb_regs[_R9]           = ti->cpu_context.r9;
+       gdb_regs[_R10]          = ti->cpu_context.sl;
+       gdb_regs[_FP]           = ti->cpu_context.fp;
+       gdb_regs[_SPT]          = ti->cpu_context.sp;
+       gdb_regs[_PC]           = ti->cpu_context.pc;
+
+       /*
+        * task_thread_info() doesn't store callee-saved registers so we'll
+        * give task_pt_regs() a shot here.  I've never actually seen that be
+        * valid, though
+        */
        thread_regs             = task_pt_regs(task);
        gdb_regs[_R0]           = thread_regs->ARM_r0;
        gdb_regs[_R1]           = thread_regs->ARM_r1;
        gdb_regs[_R2]           = thread_regs->ARM_r2;
        gdb_regs[_R3]           = thread_regs->ARM_r3;
-       gdb_regs[_R4]           = thread_regs->ARM_r4;
-       gdb_regs[_R5]           = thread_regs->ARM_r5;
-       gdb_regs[_R6]           = thread_regs->ARM_r6;
-       gdb_regs[_R7]           = thread_regs->ARM_r7;
-       gdb_regs[_R8]           = thread_regs->ARM_r8;
-       gdb_regs[_R9]           = thread_regs->ARM_r9;
-       gdb_regs[_R10]          = thread_regs->ARM_r10;
-       gdb_regs[_FP]           = thread_regs->ARM_fp;
        gdb_regs[_IP]           = thread_regs->ARM_ip;
-       gdb_regs[_SPT]          = thread_regs->ARM_sp;
        gdb_regs[_LR]           = thread_regs->ARM_lr;
-       gdb_regs[_PC]           = thread_regs->ARM_pc;
        gdb_regs[_CPSR]         = thread_regs->ARM_cpsr;
 }
 
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to