[commit] Unwinder for OpenBSD/sparc64 kernel trap frames

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[commit] Unwinder for OpenBSD/sparc64 kernel trap frames

Mark Kettenis
With this patch and a current OpenBSD/sparc64 I can actually debug
kernel core dump files.

Committed,

Mark

Index: ChangeLog
from  Mark Kettenis  <[hidden email]>

        * sparc64-tdep.h (SPARC64_PSTATE_AG, SPARC64_PSTATE_IE)
        (SPARC64_PSTATE_PRIV, SPARC64_PSTATE_AM, SPARC64_PSTATE_PEF)
        (SPARC64_PSTATE_RED, SPARC64_PSTATE_TLE, SPARC64_PSTATE_CLE)
        (SPARC64_PSTATE_PID0, SPARC64_PSTATE_PID1): New defines.
        * sparc64nbsd-nat.c: Include "gdbcore.h".
        (sparc64nbsd_supply_pcb): Get %pc from stack if necessary.  Supply
        processor state register.
        * sparc64obsd-tdep.c (sparc64obsd_trapframe_cache)
        (sparc64obsd_trapframe_this_id)
        (sparc64obsd_trapframe_prev_register)
        (sparc64obsd_trapframe_sniffer): New functions.
        (sparc64obsd_trapframe_unwind): New variable.
        (sparc64obsd_init_abi): Append trapframe unwinder.
        * Makefile.in (sparc64nbsd-nat.o): Update dependencies.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.861
diff -u -p -r1.861 Makefile.in
--- Makefile.in 17 Dec 2006 13:30:43 -0000 1.861
+++ Makefile.in 31 Dec 2006 00:42:58 -0000
@@ -2676,8 +2676,8 @@ sparc64-linux-tdep.o: sparc64-linux-tdep
  $(trad_frame_h) $(tramp_frame_h) $(sparc64_tdep_h)
 sparc64-nat.o: sparc64-nat.c $(defs_h) $(gdbarch_h) $(sparc64_tdep_h) \
  $(sparc_nat_h)
-sparc64nbsd-nat.o: sparc64nbsd-nat.c $(defs_h) $(regcache_h) $(target_h) \
- $(sparc64_tdep_h) $(sparc_nat_h) $(bsd_kvm_h)
+sparc64nbsd-nat.o: sparc64nbsd-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
+ $(target_h) $(sparc64_tdep_h) $(sparc_nat_h) $(bsd_kvm_h)
 sparc64nbsd-tdep.o: sparc64nbsd-tdep.c $(defs_h) $(frame_h) \
  $(frame_unwind_h) $(gdbcore_h) $(osabi_h) $(regcache_h) $(regset_h) \
  $(symtab_h) $(objfiles_h) $(solib_svr4_h) $(trad_frame_h) \
Index: sparc64-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-tdep.h,v
retrieving revision 1.6
diff -u -p -r1.6 sparc64-tdep.h
--- sparc64-tdep.h 17 Dec 2005 22:34:02 -0000 1.6
+++ sparc64-tdep.h 31 Dec 2006 00:42:58 -0000
@@ -1,6 +1,6 @@
 /* Target-dependent code for UltraSPARC.
 
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -84,6 +84,18 @@ enum sparc64_regnum
   = SPARC64_Q0_REGNUM + 15
 };
 
+/* Processor state bits.  */
+#define SPARC64_PSTATE_AG 0x001
+#define SPARC64_PSTATE_IE 0x002
+#define SPARC64_PSTATE_PRIV 0x004
+#define SPARC64_PSTATE_AM 0x008
+#define SPARC64_PSTATE_PEF 0x010
+#define SPARC64_PSTATE_RED 0x020
+#define SPARC64_PSTATE_TLE 0x100
+#define SPARC64_PSTATE_CLE 0x200
+#define SPARC64_PSTATE_PID0 0x400
+#define SPARC64_PSTATE_PID1 0x800
+
 extern void sparc64_init_abi (struct gdbarch_info info,
       struct gdbarch *gdbarch);
 
Index: sparc64nbsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64nbsd-nat.c,v
retrieving revision 1.7
diff -u -p -r1.7 sparc64nbsd-nat.c
--- sparc64nbsd-nat.c 17 Dec 2005 22:34:02 -0000 1.7
+++ sparc64nbsd-nat.c 31 Dec 2006 00:42:58 -0000
@@ -1,6 +1,6 @@
 /* Native-dependent code for NetBSD/sparc64.
 
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -20,6 +20,7 @@
    Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
+#include "gdbcore.h"
 #include "regcache.h"
 #include "target.h"
 
@@ -136,6 +137,7 @@ sparc64nbsd_fpregset_supplies_p (int reg
 static int
 sparc64nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 {
+  u_int64_t state;
   int regnum;
 
   /* The following is true for NetBSD 1.6.2:
@@ -148,9 +150,19 @@ sparc64nbsd_supply_pcb (struct regcache
   if (pcb->pcb_sp == 0)
     return 0;
 
+  /* If the program counter is zero, this is probably a core dump, and
+     we can get %pc from the stack.  */
+  if (pcb->pcb_pc == 0)
+      read_memory(pcb->pcb_sp + BIAS - 176 + (11 * 8),
+  (gdb_byte *)&pcb->pcb_pc, sizeof pcb->pcb_pc);
+
+
   regcache_raw_supply (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp);
   regcache_raw_supply (regcache, SPARC64_PC_REGNUM, &pcb->pcb_pc);
 
+  state = pcb->pcb_pstate << 8 | pcb->pcb_cwp;
+  regcache_raw_supply (regcache, SPARC64_STATE_REGNUM, &state);
+
   sparc_supply_rwindow (regcache, pcb->pcb_sp, -1);
 
   return 1;
Index: sparc64obsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64obsd-tdep.c,v
retrieving revision 1.19
diff -u -p -r1.19 sparc64obsd-tdep.c
--- sparc64obsd-tdep.c 22 Jan 2006 20:07:38 -0000 1.19
+++ sparc64obsd-tdep.c 31 Dec 2006 00:42:58 -0000
@@ -202,6 +202,86 @@ sparc64obsd_sigtramp_frame_sniffer (stru
   return NULL;
 }
 
+/* Kernel debugging support.  */
+
+static struct sparc_frame_cache *
+sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache)
+{
+  struct sparc_frame_cache *cache;
+  CORE_ADDR sp, trapframe_addr;
+  int regnum;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = sparc_frame_cache (next_frame, this_cache);
+  gdb_assert (cache == *this_cache);
+
+  sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
+  trapframe_addr = sp + BIAS + 176;
+
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr;
+  cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8;
+  cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16;
+
+  for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
+    cache->saved_regs[regnum].addr =
+      trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8;
+
+  return cache;
+}
+
+static void
+sparc64obsd_trapframe_this_id (struct frame_info *next_frame,
+       void **this_cache, struct frame_id *this_id)
+{
+  struct sparc_frame_cache *cache =
+    sparc64obsd_trapframe_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+sparc64obsd_trapframe_prev_register (struct frame_info *next_frame,
+     void **this_cache,
+     int regnum, int *optimizedp,
+     enum lval_type *lvalp, CORE_ADDR *addrp,
+     int *realnump, gdb_byte *valuep)
+{
+  struct sparc_frame_cache *cache =
+    sparc64obsd_trapframe_cache (next_frame, this_cache);
+
+  trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind sparc64obsd_trapframe_unwind =
+{
+  NORMAL_FRAME,
+  sparc64obsd_trapframe_this_id,
+  sparc64obsd_trapframe_prev_register
+};
+
+static const struct frame_unwind *
+sparc64obsd_trapframe_sniffer (struct frame_info *next_frame)
+{
+  ULONGEST pstate;
+  char *name;
+
+  /* Check whether we are in privileged mode, and bail out if we're not.  */
+  pstate = frame_unwind_register_unsigned(next_frame, SPARC64_PSTATE_REGNUM);
+  if ((pstate & SPARC64_PSTATE_PRIV) == 0)
+    return NULL;
+
+  find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
+  if (name && strcmp (name, "Lslowtrap_reenter") == 0)
+    return &sparc64obsd_trapframe_unwind;
+
+  return NULL;
+}
+
 
 /* Threads support.  */
 
@@ -299,6 +379,7 @@ sparc64obsd_init_abi (struct gdbarch_inf
   tdep->step_trap = sparcnbsd_step_trap;
 
   frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer);
+  frame_unwind_append_sniffer (gdbarch, sparc64obsd_trapframe_sniffer);
 
   sparc64_init_abi (info, gdbarch);
 

Reply | Threaded
Open this post in threaded view
|

Re: [commit] Unwinder for OpenBSD/sparc64 kernel trap frames

Daniel Jacobowitz-2
On Sun, Dec 31, 2006 at 02:28:13AM +0100, Mark Kettenis wrote:
> +  find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
> +  if (name && strcmp (name, "Lslowtrap_reenter") == 0)
> +    return &sparc64obsd_trapframe_unwind;

Does this really belong in GDB?  I ask because we've resisted adding
similar things for other targets before - at least I have for Linux
and for Xfree86, but maybe I should have been more accepting.

Anyway, I have some thoughts on how to extend the unwind mechanism so
that the OpenBSD kernel could ship a script that knew how to unwind its
trap frames.  I'll be posting about that at the beginning of 2007, just
as soon as I clear my review backlog and the pointers-to-members patch,
I hope!

--
Daniel Jacobowitz
CodeSourcery
Reply | Threaded
Open this post in threaded view
|

Re: [commit] Unwinder for OpenBSD/sparc64 kernel trap frames

Mark Kettenis
> Date: Sat, 30 Dec 2006 21:22:59 -0500
> From: Daniel Jacobowitz <[hidden email]>
>
> On Sun, Dec 31, 2006 at 02:28:13AM +0100, Mark Kettenis wrote:
> > +  find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
> > +  if (name && strcmp (name, "Lslowtrap_reenter") == 0)
> > +    return &sparc64obsd_trapframe_unwind;
>
> Does this really belong in GDB?  I ask because we've resisted adding
> similar things for other targets before - at least I have for Linux
> and for Xfree86, but maybe I should have been more accepting.

Heh, I believe you raised the same question when I added the same code
to i386 and amd64.  At that time I believe I convinced you that this
was acceptable.  This is not very invasive and nicely contained in
*BSD-specific files.  And the layout of kernel trapframes is pretty
stable.

GDB has been shipping with *BSD kernel debugging support for ages,
although it probably was almost completely broken until I cleaned
things up and replaced it with the kvm target a while ago.

I have looked into adding the XFree86 support too, but that was much
more invasive (because weirdness in their "dynamic linker"
implementation and problems with our shared library framework).  And
these days on OpenBSD, XOrg uses the normal ld.so to load modules.

Adding Linux kernel debugging support is much harder.  The rate of
change is much higher, there are kernel modules (which have a slightly
odd format).  And of course Linux doesn't have kernel core dumps, so
it would only be useful to debug a live kernel.

> Anyway, I have some thoughts on how to extend the unwind mechanism so
> that the OpenBSD kernel could ship a script that knew how to unwind its
> trap frames.

Did you really mean to say OpenBSD here?

Mark
Reply | Threaded
Open this post in threaded view
|

Re: [commit] Unwinder for OpenBSD/sparc64 kernel trap frames

Daniel Jacobowitz-2
On Sun, Dec 31, 2006 at 01:36:38PM +0100, Mark Kettenis wrote:
> Heh, I believe you raised the same question when I added the same code
> to i386 and amd64.  At that time I believe I convinced you that this
> was acceptable.

Oh right :-)  Shows you what my memory is worth these days.

> Adding Linux kernel debugging support is much harder.  The rate of
> change is much higher, there are kernel modules (which have a slightly
> odd format).  And of course Linux doesn't have kernel core dumps, so
> it would only be useful to debug a live kernel.

I'm not sure about all of these, except the last one - there's at least
one implementation of crash dumps for Linux.  It's still not common,
though, more's the pity.

> > Anyway, I have some thoughts on how to extend the unwind mechanism so
> > that the OpenBSD kernel could ship a script that knew how to unwind its
> > trap frames.
>
> Did you really mean to say OpenBSD here?

Well, *BSD.  I mean, specifically, a script that does the same thing
the patch to sparc64obsd-tdep.c does.  Whether it actually gets bundled
with OpenBSD or with GDB is an interesting question, I guess :-)

--
Daniel Jacobowitz
CodeSourcery