This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] sigaltstack fixes for hppa-linux


This patch fixes sigaltstack handling on hppa. It requires one arch-indep 
change in frame.c: on hppa (stack-grows-up), the relationship of the 
sigaltstack can be that it is not "inner" to the signal frame, if the 
sigaltstack resides in a caller's stack frame (as is true in gdb's testcase.)

ok to apply?

2004-05-03  Randolph Chung  <tausq@debian.org>

	* frame.c (get_prev_frame_1): Relax frame_id_inner check for 
	SIGTRAMP_FRAME.
	* hppa-linux-tdep.c (hppa_linux_sigtramp_find_sigcontext): Pass in pc
	instead of sp, handle sigaltstack case.
	(hppa_linux_sigtramp_frame_unwind_cache)
	(hppa_linux_sigtramp_unwind_sniffer): Adjust calls to
	hppa_linux_sigtramp_find_sigcontext.

Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.173
diff -u -p -r1.173 frame.c
--- frame.c	26 Apr 2004 09:49:35 -0000	1.173
+++ frame.c	4 May 2004 14:43:32 -0000
@@ -1794,6 +1794,7 @@ get_prev_frame_1 (struct frame_info *thi
      Exclude signal trampolines (due to sigaltstack the frame ID can
      go backwards) and sentinel frames (the test is meaningless).  */
   if (this_frame->next->level >= 0
+      && this_frame->type != SIGTRAMP_FRAME
       && this_frame->next->type != SIGTRAMP_FRAME
       && frame_id_inner (get_frame_id (this_frame),
 			 get_frame_id (this_frame->next)))
Index: hppa-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-linux-tdep.c,v
retrieving revision 1.1
diff -u -p -r1.1 hppa-linux-tdep.c
--- hppa-linux-tdep.c	29 Apr 2004 03:36:49 -0000	1.1
+++ hppa-linux-tdep.c	4 May 2004 14:43:32 -0000
@@ -282,7 +282,7 @@ hppa_linux_skip_trampoline_code (CORE_AD
    Note that with a 2.4 64-bit kernel, the signal context is not properly
    passed back to userspace so the unwind will not work correctly.  */
 static CORE_ADDR
-hppa_linux_sigtramp_find_sigcontext (CORE_ADDR sp)
+hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc)
 {
   unsigned int dummy[HPPA_MAX_INSN_PATTERN_LEN];
   int offs = 0;
@@ -291,6 +291,12 @@ hppa_linux_sigtramp_find_sigcontext (COR
   static int pcoffs[] = { 0, 4*4, 5*4 };
   /* offsets to the rt_sigframe structure */
   static int sfoffs[] = { 4*4, 10*4, 10*4 };
+  CORE_ADDR sp;
+
+  /* Most of the time, this will be correct.  The one case when this will
+     fail is if the user defined an alternate stack, in which case the
+     beginning of the stack will not be pc & 63.  */
+  sp = (pc & ~63);
 
   /* rt_sigreturn trampoline:
      3419000x ldi 0, %r25 or ldi 1, %r25   (x = 0 or 2)
@@ -308,7 +314,18 @@ hppa_linux_sigtramp_find_sigcontext (COR
     }
 
   if (offs == 0)
-    return 0;
+    {
+      if (insns_match_pattern (pc, hppa_sigtramp, dummy))
+	{
+	  /* sigaltstack case: we have no way of knowing which offset to 
+	     use in this case; default to new kernel handling. If this is
+	     wrong the unwinding will fail.  */
+	  try = 2;
+	  sp = pc - pcoffs[try];
+	}
+      else
+        return 0;
+    }
 
   /* sp + sfoffs[try] points to a struct rt_sigframe, which contains
      a struct siginfo and a struct ucontext.  struct ucontext contains
@@ -331,7 +348,7 @@ hppa_linux_sigtramp_frame_unwind_cache (
 {
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
   struct hppa_linux_sigtramp_unwind_cache *info;
-  CORE_ADDR sp, pc, scptr;
+  CORE_ADDR pc, scptr;
   int i;
 
   if (*this_cache)
@@ -342,8 +359,7 @@ hppa_linux_sigtramp_frame_unwind_cache (
   info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
   pc = frame_pc_unwind (next_frame);
-  sp = (pc & ~63);
-  scptr = hppa_linux_sigtramp_find_sigcontext (sp);
+  scptr = hppa_linux_sigtramp_find_sigcontext (pc);
 
   /* structure of struct sigcontext:
    
@@ -448,14 +464,13 @@ static const struct frame_unwind *
 hppa_linux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
 {
   CORE_ADDR pc = frame_pc_unwind (next_frame);
-  CORE_ADDR sp = (pc & ~63);
 
-  if (hppa_linux_sigtramp_find_sigcontext (sp))
+  if (hppa_linux_sigtramp_find_sigcontext (pc))
     return &hppa_linux_sigtramp_frame_unwind;
 
   return NULL;
 }
 
 /* Forward declarations.  */
 extern initialize_file_ftype _initialize_hppa_linux_tdep;
 
-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]