Blob Blame History Raw
2005-09-27  Jeff Johnston  <jjohnstn@redhat.com>

	* libunwind-frame.c (libunwind_frame_cache): Save the current
	stack pointer in the cache.
	(libunwind_sigtramp_frame_this_id): New function.
	(libunwind_sigtramp_frame_unwind): New unwinder.
	(libunwind_sigtramp_frame_sniffer): Return 
	libunwind_sigtramp_frame_unwind address.
	* libunwind-frame.h (libunwind_sigtramp_frame_this_id): New
	prototype.
	* ia64-tdep.c (ia64_libunwind_sigtramp_frame_this_id): Calculate
	the base address using the current stack pointer plus a fixed
	offset.

2007-10-14  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Port to GDB-6.7.

2008-02-24  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Port to GDB-6.8pre.

Index: gdb-6.8cvs20080219/gdb/libunwind-frame.c
===================================================================
--- gdb-6.8cvs20080219.orig/gdb/libunwind-frame.c	2008-01-02 00:04:03.000000000 +0100
+++ gdb-6.8cvs20080219/gdb/libunwind-frame.c	2008-02-24 20:25:56.000000000 +0100
@@ -61,6 +61,7 @@ static unw_word_t (*unw_find_dyn_list_p)
 struct libunwind_frame_cache
 {
   CORE_ADDR base;
+  CORE_ADDR sp;
   CORE_ADDR func_addr;
   unw_cursor_t cursor;
   unw_addr_space_t as;
@@ -133,6 +134,7 @@ libunwind_frame_cache (struct frame_info
   unw_accessors_t *acc;
   unw_addr_space_t as;
   unw_word_t fp;
+  unw_word_t fp, sp;
   unw_regnum_t uw_sp_regnum;
   struct libunwind_frame_cache *cache;
   struct libunwind_descr *descr;
@@ -171,14 +173,30 @@ libunwind_frame_cache (struct frame_info
 				 : __LITTLE_ENDIAN);
 
   unw_init_remote_p (&cache->cursor, as, next_frame);
+
+  /* For the base address, we have a small problem.  The majority
+     of the time, we can get the stack pointer of the previous
+     frame to use as a frame pointer.  In the case where we have
+     a signal trampoline, the stack may change due to a sigaltstack
+     being set up.  In that case, the normal mechanism will give us
+     an address in the regular stack which is not at the end of the
+     sigaltstack as we want.  To handle this, we record the stack
+     address so the caller may calculate a more correct base address
+     to use.  */
+  uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch));
+  ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &sp);
+  if (ret < 0)
+    {
+      unw_destroy_addr_space_p (as);
+      error (_("Can't get libunwind sp register."));
+    }
+
   if (unw_step_p (&cache->cursor) < 0)
     {
       unw_destroy_addr_space_p (as);
       return NULL;
     }
 
-  /* To get base address, get sp from previous frame.  */
-  uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch));
   ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp);
   if (ret < 0)
     {
@@ -186,6 +204,7 @@ libunwind_frame_cache (struct frame_info
       error (_("Can't get libunwind sp register."));
     }
 
+  cache->sp = (CORE_ADDR)sp;
   cache->base = (CORE_ADDR)fp;
   cache->as = as;
 
@@ -381,6 +400,31 @@ libunwind_search_unwind_table (void *as,
 				    di, pi, need_unwind_info, args);
 }
 
+void
+libunwind_sigtramp_frame_this_id (struct frame_info *next_frame, 
+				  void **this_cache,
+		      		  struct frame_id *this_id)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  /* Unlike a regular frame, we can't use the normal frame pointer
+     mechanism because a sigaltstack may have been used.  Instead,
+     we return the current stack pointer for the caller to use
+     to calculate the base address.  */
+  if (cache != NULL)
+    (*this_id) = frame_id_build (cache->sp, cache->func_addr);
+  else
+    (*this_id) = null_frame_id;
+}
+
+static const struct frame_unwind libunwind_sigtramp_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  libunwind_sigtramp_frame_this_id,
+  libunwind_frame_prev_register
+};
+
 /* Verify if we are in a sigtramp frame and we can use libunwind to unwind.  */
 const struct frame_unwind *
 libunwind_sigtramp_frame_sniffer (struct frame_info *next_frame)
@@ -419,7 +463,7 @@ libunwind_sigtramp_frame_sniffer (struct
   ret = unw_is_signal_frame_p (&cursor);
   unw_destroy_addr_space_p (as);
   if (ret > 0)
-    return &libunwind_frame_unwind;
+    return &libunwind_sigtramp_frame_unwind;
 
   return NULL;
 }
Index: gdb-6.8cvs20080219/gdb/libunwind-frame.h
===================================================================
--- gdb-6.8cvs20080219.orig/gdb/libunwind-frame.h	2008-01-02 00:04:03.000000000 +0100
+++ gdb-6.8cvs20080219/gdb/libunwind-frame.h	2008-02-24 20:23:47.000000000 +0100
@@ -47,6 +47,9 @@ void libunwind_frame_set_descr (struct g
 
 void libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
 			      struct frame_id *this_id);
+void libunwind_sigtramp_frame_this_id (struct frame_info *next_frame, 
+				       void **this_cache,
+			      	       struct frame_id *this_id);
 void libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
 				    int regnum, int *optimizedp,
 				    enum lval_type *lvalp, CORE_ADDR *addrp,
Index: gdb-6.8cvs20080219/gdb/ia64-tdep.c
===================================================================
--- gdb-6.8cvs20080219.orig/gdb/ia64-tdep.c	2008-02-24 20:23:40.000000000 +0100
+++ gdb-6.8cvs20080219/gdb/ia64-tdep.c	2008-02-24 20:23:47.000000000 +0100
@@ -2942,7 +2942,7 @@ ia64_libunwind_sigtramp_frame_this_id (s
   struct frame_id id;
   CORE_ADDR prev_ip;
 
-  libunwind_frame_this_id (next_frame, this_cache, &id);
+  libunwind_sigtramp_frame_this_id (next_frame, this_cache, &id);
   if (frame_id_eq (id, null_frame_id))
     {
       (*this_id) = null_frame_id;
@@ -2954,8 +2954,14 @@ ia64_libunwind_sigtramp_frame_this_id (s
   frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
   bsp = extract_unsigned_integer (buf, 8);
 
-  /* For a sigtramp frame, we don't make the check for previous ip being 0.  */
-  (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp);
+  /* For a sigtramp frame, we don't make the check for previous ip being 0.  
+     We also must calculate the frame pointer because libunwind will give
+     us back the current stack pointer instead of the frame pointer since
+     it cannot figure this out when in a sigaltstack.  We make a basic
+     assumption of 16 (default size) + 8 bytes for sigcontext address.
+     FIXME: if libunwind were to export the frame pointer address, we
+            could eliminate the assumption and get the actual value.  */
+  (*this_id) = frame_id_build_special (id.stack_addr + 24, id.code_addr, bsp);
 
   if (gdbarch_debug >= 1)
     fprintf_unfiltered (gdb_stdlog,