2004-05-07 Randolph Chung <tausq@debian.org>
authorRandolph Chung <tausq@debian.org>
Sat, 8 May 2004 03:17:57 +0000 (03:17 +0000)
committerRandolph Chung <tausq@debian.org>
Sat, 8 May 2004 03:17:57 +0000 (03:17 +0000)
* hppa-tdep.c (hppa_frame_prev_register_helper): New function to
do common handling of the pcoqt register.
(hppa_frame_prev_register, hppa_stub_frame_prev_register): Convert
to use helper function.
(hppa_frame_unwind_sniffer): Only use if unwind entry is present.
(hppa_fallback_frame_cache, hppa_fallback_frame_this_id)
(hppa_fallback_frame_prev_register, hppa_fallback_frame_unwind): New
generic fallback unwinder when all else fails.
(hppa_gdbarch_init): Add fallback sniffer.
* hppa-tdep.h (hppa_frame_prev_register_helper): Prototype.
* hppa-linux-tdep.c (hppa_linux_sigtramp_frame_prev_register): Convert
to use helper function.

gdb/ChangeLog
gdb/hppa-linux-tdep.c
gdb/hppa-tdep.c
gdb/hppa-tdep.h

index e81bcf0..a4484fe 100644 (file)
@@ -1,3 +1,18 @@
+2004-05-07  Randolph Chung  <tausq@debian.org>
+
+       * hppa-tdep.c (hppa_frame_prev_register_helper): New function to 
+       do common handling of the pcoqt register.
+       (hppa_frame_prev_register, hppa_stub_frame_prev_register): Convert
+       to use helper function.
+       (hppa_frame_unwind_sniffer): Only use if unwind entry is present.
+       (hppa_fallback_frame_cache, hppa_fallback_frame_this_id)
+       (hppa_fallback_frame_prev_register, hppa_fallback_frame_unwind): New
+       generic fallback unwinder when all else fails.
+       (hppa_gdbarch_init): Add fallback sniffer.
+       * hppa-tdep.h (hppa_frame_prev_register_helper): Prototype.
+       * hppa-linux-tdep.c (hppa_linux_sigtramp_frame_prev_register): Convert
+       to use helper function.
+
 2004-05-08  Joel Brobecker  <brobecker@gnat.com>
 
        * config/djgpp/fnchange.lst: Add translation rules for
index 1d7d047..8fae030 100644 (file)
@@ -415,21 +415,12 @@ hppa_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
                                         int regnum, int *optimizedp,
                                         enum lval_type *lvalp, 
                                         CORE_ADDR *addrp,
-                                        int *realnump, void *bufferp)
+                                        int *realnump, void *valuep)
 {
   struct hppa_linux_sigtramp_unwind_cache *info
     = hppa_linux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
-  int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM);
-
-  if (pcoqt)
-    regnum = HPPA_PCOQ_HEAD_REGNUM;
-
-  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
-                            optimizedp, lvalp, addrp, realnump, bufferp);
-
-  if (pcoqt)
-    store_unsigned_integer (bufferp, 4, 
-                           extract_unsigned_integer (bufferp, 4) + 4);
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
 }
 
 static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = {
index 9ead808..3e0e0ab 100644 (file)
@@ -1856,55 +1856,136 @@ hppa_frame_this_id (struct frame_info *next_frame, void **this_cache,
 
 static void
 hppa_frame_prev_register (struct frame_info *next_frame,
-                                void **this_cache,
-                                int regnum, int *optimizedp,
-                                enum lval_type *lvalp, CORE_ADDR *addrp,
-                                int *realnump, void *valuep)
+                         void **this_cache,
+                         int regnum, int *optimizedp,
+                         enum lval_type *lvalp, CORE_ADDR *addrp,
+                         int *realnump, void *valuep)
 {
   struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache);
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  if (regnum == HPPA_PCOQ_TAIL_REGNUM)
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind hppa_frame_unwind =
+{
+  NORMAL_FRAME,
+  hppa_frame_this_id,
+  hppa_frame_prev_register
+};
+
+static const struct frame_unwind *
+hppa_frame_unwind_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+
+  if (find_unwind_entry (pc))
+    return &hppa_frame_unwind;
+
+  return NULL;
+}
+
+/* This is a generic fallback frame unwinder that kicks in if we fail all
+   the other ones.  Normally we would expect the stub and regular unwinder
+   to work, but in some cases we might hit a function that just doesn't
+   have any unwind information available.  In this case we try to do
+   unwinding solely based on code reading.  This is obviously going to be
+   slow, so only use this as a last resort.  Currently this will only
+   identify the stack and pc for the frame.  */
+
+static struct hppa_frame_cache *
+hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct hppa_frame_cache *cache;
+  CORE_ADDR pc, start_pc, end_pc, cur_pc;
+
+  cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  pc = frame_func_unwind (next_frame);
+  cur_pc = frame_pc_unwind (next_frame);
+
+  find_pc_partial_function (pc, NULL, &start_pc, &end_pc);
+
+  if (start_pc == 0 || end_pc == 0)
     {
-      /* The PCOQ TAIL, or NPC, needs to be computed from the unwound
-        PC register.  */
-      *optimizedp = 0;
-      *lvalp = not_lval;
-      *addrp = 0;
-      *realnump = 0;
-      if (valuep)
+      error ("Cannot find bounds of current function (@0x%s), unwinding will "
+            "fail.", paddr_nz (pc));
+      return cache;
+    }
+
+  if (end_pc > cur_pc)
+    end_pc = cur_pc;
+
+  for (pc = start_pc; pc < end_pc; pc += 4)
+    {
+      unsigned int insn;
+
+      insn = read_memory_unsigned_integer (pc, 4);
+
+      /* There are limited ways to store the return pointer into the
+        stack.  */
+      if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
+       {
+         cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
+         break;
+       }
+      else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
        {
-         int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM);
-         CORE_ADDR pc;
-         int optimized;
-         enum lval_type lval;
-         CORE_ADDR addr;
-         int realnum;
-         bfd_byte value[MAX_REGISTER_SIZE];
-         trad_frame_prev_register (next_frame, info->saved_regs,
-                                   HPPA_PCOQ_HEAD_REGNUM, &optimized, &lval, &addr,
-                                   &realnum, &value);
-         pc = extract_unsigned_integer (&value, regsize);
-         store_unsigned_integer (valuep, regsize, pc + 4);
+         cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
+         break;
        }
     }
+
+  cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+
+  if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
+    {
+      cache->saved_regs[HPPA_RP_REGNUM].addr += cache->base;
+      cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM];
+    }
   else
     {
-      trad_frame_prev_register (next_frame, info->saved_regs, regnum,
-                               optimizedp, lvalp, addrp, realnump, valuep);
+      ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM);
+      trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp);
     }
+
+  return cache;
 }
 
-static const struct frame_unwind hppa_frame_unwind =
+static void
+hppa_fallback_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                            struct frame_id *this_id)
+{
+  struct hppa_frame_cache *info = 
+    hppa_fallback_frame_cache (next_frame, this_cache);
+  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+}
+
+static void
+hppa_fallback_frame_prev_register (struct frame_info *next_frame,
+                         void **this_cache,
+                         int regnum, int *optimizedp,
+                         enum lval_type *lvalp, CORE_ADDR *addrp,
+                         int *realnump, void *valuep)
+{
+  struct hppa_frame_cache *info = 
+    hppa_fallback_frame_cache (next_frame, this_cache);
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind hppa_fallback_frame_unwind =
 {
   NORMAL_FRAME,
-  hppa_frame_this_id,
-  hppa_frame_prev_register
+  hppa_fallback_frame_this_id,
+  hppa_fallback_frame_prev_register
 };
 
 static const struct frame_unwind *
-hppa_frame_unwind_sniffer (struct frame_info *next_frame)
+hppa_fallback_unwind_sniffer (struct frame_info *next_frame)
 {
-  return &hppa_frame_unwind;
+  return &hppa_fallback_frame_unwind;
 }
 
 static CORE_ADDR
@@ -1971,23 +2052,12 @@ hppa_stub_frame_prev_register (struct frame_info *next_frame,
                               void **this_prologue_cache,
                               int regnum, int *optimizedp,
                               enum lval_type *lvalp, CORE_ADDR *addrp,
-                              int *realnump, void *bufferp)
+                              int *realnump, void *valuep)
 {
   struct hppa_stub_unwind_cache *info
     = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache);
-  int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM);
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM);
-
-  if (pcoqt)
-    regnum = HPPA_PCOQ_HEAD_REGNUM;
-
-  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
-                            optimizedp, lvalp, addrp, realnump, bufferp);
-
-  if (pcoqt)
-    store_unsigned_integer (bufferp, regsize, 
-                           extract_unsigned_integer (bufferp, regsize) + 4);
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
 }
 
 static const struct frame_unwind hppa_stub_frame_unwind = {
@@ -2230,6 +2300,28 @@ hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     store_unsigned_integer (buf, sizeof(tmp), tmp);
 }
 
+void
+hppa_frame_prev_register_helper (struct frame_info *next_frame,
+                                struct trad_frame_saved_reg saved_regs[],
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
+{
+  int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM);
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM);
+
+  if (pcoqt)
+    regnum = HPPA_PCOQ_HEAD_REGNUM;
+
+  trad_frame_prev_register (next_frame, saved_regs, regnum,
+                            optimizedp, lvalp, addrp, realnump, valuep);
+
+  if (pcoqt)
+    store_unsigned_integer (valuep, regsize, 
+                           extract_unsigned_integer (valuep, regsize) + 4);
+}
+
 /* Here is a table of C type sizes on hppa with various compiles
    and options.  I measured this on PA 9000/800 with HP-UX 11.11
    and these compilers:
@@ -2391,6 +2483,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Hook in the default unwinders.  */
   frame_unwind_append_sniffer (gdbarch, hppa_stub_unwind_sniffer);
   frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
+  frame_unwind_append_sniffer (gdbarch, hppa_fallback_unwind_sniffer);
   frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
 
   return gdbarch;
index 79e8ae3..55c8bda 100644 (file)
@@ -188,4 +188,11 @@ int hppa_extract_14 (unsigned);
 int hppa_low_sign_extend (unsigned int, unsigned int);
 int hppa_sign_extend (unsigned int, unsigned int);
 
+void
+hppa_frame_prev_register_helper (struct frame_info *next_frame,
+                                struct trad_frame_saved_reg saved_regs[],
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep);
+
 #endif  /* HPPA_TDEP_H */