72cd19d
2005-07-11  Jeff Johnston  <jjohnstn@redhat.com>
72cd19d
72cd19d
	* ia64-tdep.c (pseudo_regs): Add CURSOR_ADDR_REGNUM.
72cd19d
	(ia64_register_names): Add empty string for CURSOR_ADDR_REGNUM.
72cd19d
	(ia64_frame_prev_register): Default a request for CURSOR_ADDR_REGNUM
72cd19d
	to return 0.
72cd19d
	(ia64_sigtramp_frame_prev_register): Ditto.
72cd19d
	(ia64_gdb2uw_regnum): Map CURSOR_ADDR_REGNUM to INT_MAX so
72cd19d
	it won't clash with any legitimate UNW register number.
72cd19d
	(ia64_unwind_cursor): New callback.
72cd19d
	(ia64_libunwind_descr): Add new ia64_unwind_cursor callback.
72cd19d
	* libunwind-frame.h (struct libunwind_descr): Add new slot
72cd19d
	for unwind cursor callback.
72cd19d
	* libunwind-frame.c (libunwind_frame_cache): Attempt to copy
72cd19d
	and step previous cursor if possible, otherwise, create new
72cd19d
	cursor.
72cd19d
	(libunwind_frame_prev_register): Support request for
72cd19d
	getting the cursor address.
72cd19d
72cd19d
--- gdb-6.3/gdb/ia64-tdep.c.fix	2005-07-11 18:13:42.000000000 -0400
72cd19d
+++ gdb-6.3/gdb/ia64-tdep.c	2005-07-11 18:15:52.000000000 -0400
72cd19d
@@ -141,7 +141,7 @@ static int lr_regnum = IA64_VRAP_REGNUM;
72cd19d
    they may not be accessible via the ptrace register get/set interfaces.  */
72cd19d
 enum pseudo_regs { FIRST_PSEUDO_REGNUM = NUM_IA64_RAW_REGS, VBOF_REGNUM = IA64_NAT127_REGNUM + 1, V32_REGNUM, 
72cd19d
 		   V127_REGNUM = V32_REGNUM + 95, 
72cd19d
-		   VP0_REGNUM, VP16_REGNUM = VP0_REGNUM + 16, VP63_REGNUM = VP0_REGNUM + 63, LAST_PSEUDO_REGNUM };
72cd19d
+		   VP0_REGNUM, VP16_REGNUM = VP0_REGNUM + 16, VP63_REGNUM = VP0_REGNUM + 63, CURSOR_ADDR_REGNUM, LAST_PSEUDO_REGNUM };
72cd19d
 
72cd19d
 /* Array of register names; There should be ia64_num_regs strings in
72cd19d
    the initializer.  */
72cd19d
@@ -253,6 +253,7 @@ static char *ia64_register_names[] = 
72cd19d
   "p40",  "p41",  "p42",  "p43",  "p44",  "p45",  "p46",  "p47",
72cd19d
   "p48",  "p49",  "p50",  "p51",  "p52",  "p53",  "p54",  "p55",
72cd19d
   "p56",  "p57",  "p58",  "p59",  "p60",  "p61",  "p62",  "p63",
72cd19d
+  ""
72cd19d
 };
72cd19d
 
72cd19d
 struct ia64_frame_cache
72cd19d
@@ -1855,6 +1856,12 @@ ia64_frame_prev_register (struct frame_i
72cd19d
 	  read_memory (addr, valuep, register_size (current_gdbarch, regnum));
72cd19d
         }
72cd19d
     }
72cd19d
+  else if (regnum == CURSOR_ADDR_REGNUM)
72cd19d
+    {
72cd19d
+      /* The cursor is the address of the ia64 libunwind cursor.  
72cd19d
+         Default to 0.  */
72cd19d
+      *lvalp = lval_memory;
72cd19d
+    }
72cd19d
   else
72cd19d
     {
72cd19d
       CORE_ADDR addr = 0;
72cd19d
@@ -2177,6 +2184,12 @@ ia64_sigtramp_frame_prev_register (struc
72cd19d
 	  *addrp = pr_addr;
72cd19d
 	}
72cd19d
     }
72cd19d
+  else if (regnum == CURSOR_ADDR_REGNUM)
72cd19d
+    {
72cd19d
+      /* The cursor is the address of the ia64 libunwind cursor.  
72cd19d
+         Default to 0.  */
72cd19d
+      *lvalp = lval_memory;
72cd19d
+    }
72cd19d
   else
72cd19d
     {
72cd19d
       /* All other registers not listed above.  */
72cd19d
@@ -2296,6 +2309,8 @@ ia64_gdb2uw_regnum (int regnum)
72cd19d
     return UNW_IA64_AR + (regnum - IA64_AR0_REGNUM);
72cd19d
   else if ((unsigned) (regnum - IA64_NAT0_REGNUM) < 128)
72cd19d
     return UNW_IA64_NAT + (regnum - IA64_NAT0_REGNUM);
72cd19d
+  else if (regnum == CURSOR_ADDR_REGNUM)
72cd19d
+    return INT_MAX;
72cd19d
   else
72cd19d
     return -1;
72cd19d
 }
72cd19d
@@ -2331,6 +2346,21 @@ ia64_uw2gdb_regnum (int uw_regnum)
72cd19d
     return -1;
72cd19d
 }
72cd19d
 
72cd19d
+/* Special callback function to allow libunwind-frame to get
72cd19d
+   the address of the next frame's cursor so it may be copied and
72cd19d
+   stepped.  */
72cd19d
+static unw_cursor_t *
72cd19d
+ia64_unwind_cursor (struct frame_info *next_frame)
72cd19d
+{
72cd19d
+  unw_cursor_t *cursor_addr;
72cd19d
+  char buf[8];
72cd19d
+
72cd19d
+  frame_unwind_register (next_frame, CURSOR_ADDR_REGNUM, buf);
72cd19d
+  cursor_addr = (unw_cursor_t *)extract_unsigned_integer (buf, 8);
72cd19d
+
72cd19d
+  return cursor_addr;
72cd19d
+}
72cd19d
+
72cd19d
 /* Gdb libunwind-frame callback function to reveal if register is a float 
72cd19d
    register or not.  */
72cd19d
 static int
72cd19d
@@ -3111,6 +3141,7 @@ static struct libunwind_descr ia64_libun
72cd19d
   ia64_gdb2uw_regnum, 
72cd19d
   ia64_uw2gdb_regnum, 
72cd19d
   ia64_is_fpreg, 
72cd19d
+  ia64_unwind_cursor, 
72cd19d
   &ia64_unw_accessors,
72cd19d
   &ia64_unw_rse_accessors,
72cd19d
 };
72cd19d
--- gdb-6.3/gdb/libunwind-frame.c.fix	2005-07-11 18:17:05.000000000 -0400
72cd19d
+++ gdb-6.3/gdb/libunwind-frame.c	2005-07-11 18:20:31.000000000 -0400
72cd19d
@@ -122,6 +122,7 @@ libunwind_frame_set_descr (struct gdbarc
72cd19d
   arch_descr->is_fpreg = descr->is_fpreg;
72cd19d
   arch_descr->accessors = descr->accessors;
72cd19d
   arch_descr->special_accessors = descr->special_accessors;
72cd19d
+  arch_descr->unwind_cursor = descr->unwind_cursor;
72cd19d
 }
72cd19d
 
72cd19d
 static struct libunwind_frame_cache *
72cd19d
@@ -129,6 +130,7 @@ libunwind_frame_cache (struct frame_info
72cd19d
 {
72cd19d
   unw_accessors_t *acc;
72cd19d
   unw_addr_space_t as;
72cd19d
+  unw_cursor_t *cursor_addr;
72cd19d
   unw_word_t fp;
72cd19d
   unw_regnum_t uw_sp_regnum;
72cd19d
   struct libunwind_frame_cache *cache;
72cd19d
@@ -147,22 +149,33 @@ libunwind_frame_cache (struct frame_info
72cd19d
       && get_frame_type (next_frame) != SIGTRAMP_FRAME)
72cd19d
     return NULL;
72cd19d
 
72cd19d
-  /* Get a libunwind cursor to the previous frame.  We do this by initializing
72cd19d
-     a cursor.  Libunwind treats a new cursor as the top of stack and will get
72cd19d
-     the current register set via the libunwind register accessor.  Now, we
72cd19d
-     provide the platform-specific accessors and we set up the register accessor to use
72cd19d
-     the frame register unwinding interfaces so that we properly get the registers for
72cd19d
-     the current frame rather than the top.  We then use the  unw_step function to 
72cd19d
-     move the libunwind cursor back one frame.  We can later use this cursor to find previous 
72cd19d
-     registers via the unw_get_reg interface which will invoke libunwind's special logic.  */
72cd19d
+  /* Get a libunwind cursor to the previous frame.  We do this by getting
72cd19d
+     the address of the next frame's cursor (if one exists).  If we are at 
72cd19d
+     the top of stack, then we will get back a zero cursor address and we 
72cd19d
+     should initialize a new cursor.
72cd19d
+
72cd19d
+     Otherwise, we copy the cursor address contents and step back by one.
72cd19d
+     Libunwind will use our register accessors which are set up to
72cd19d
+     unwind registers from the previous frame.  We will later use this cursor
72cd19d
+     to find previous registers via the unw_get_reg interface.  By passing
72cd19d
+     back a cursor, we allow libunwind to handle sigaltstack which requires
72cd19d
+     one cursor stepped back for all frames.  */
72cd19d
   descr = libunwind_descr (get_frame_arch (next_frame));
72cd19d
-  acc = descr->accessors;
72cd19d
-  as =  unw_create_addr_space_p (acc,
72cd19d
+  cursor_addr = descr->unwind_cursor (next_frame);
72cd19d
+
72cd19d
+  if (cursor_addr == 0)
72cd19d
+    {
72cd19d
+      acc = descr->accessors;
72cd19d
+      as =  unw_create_addr_space_p (acc,
72cd19d
 				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
72cd19d
 				 ? __BIG_ENDIAN
72cd19d
 				 : __LITTLE_ENDIAN);
72cd19d
 
72cd19d
-  unw_init_remote_p (&cache->cursor, as, next_frame);
72cd19d
+      unw_init_remote_p (&cache->cursor, as, next_frame);
72cd19d
+    }
72cd19d
+  else /* make copy */
72cd19d
+    cache->cursor = *cursor_addr;
72cd19d
+
72cd19d
   if (unw_step_p (&cache->cursor) < 0)
72cd19d
     return NULL;
72cd19d
 
72cd19d
@@ -285,6 +298,16 @@ libunwind_frame_prev_register (struct fr
72cd19d
   if (uw_regnum < 0)
72cd19d
     return;
72cd19d
 
72cd19d
+  /* Check if we are unwinding the cursor address which just gives
72cd19d
+     back the address of the next frame's cursor.  This is a special
72cd19d
+     modification to support unwinding through a sigaltstack.  */
72cd19d
+  if (uw_regnum == INT_MAX)
72cd19d
+    {
72cd19d
+      store_unsigned_integer (valuep, sizeof (CORE_ADDR), 
72cd19d
+			      (CORE_ADDR)&cache->cursor);
72cd19d
+      return;
72cd19d
+    }
72cd19d
+
72cd19d
   /* To get the previous register, we use the libunwind register APIs with
72cd19d
      the cursor we have already pushed back to the previous frame.  */
72cd19d
 
72cd19d
--- gdb-6.3/gdb/libunwind-frame.h.fix	2005-07-11 18:17:24.000000000 -0400
72cd19d
+++ gdb-6.3/gdb/libunwind-frame.h	2005-07-11 18:18:46.000000000 -0400
72cd19d
@@ -37,6 +37,7 @@ struct libunwind_descr
72cd19d
   int (*gdb2uw) (int);
72cd19d
   int (*uw2gdb) (int);
72cd19d
   int (*is_fpreg) (int);
72cd19d
+  unw_cursor_t *(*unwind_cursor) (struct frame_info *next_frame);
72cd19d
   void *accessors;
72cd19d
   void *special_accessors;
72cd19d
 };