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] Add support for "frameless" signals for all i386 targets


This patch adds support for "frameless" signals (signal trampolines
invoked from a frameless function).  Basically, this code is lifted
from the Linux-psecific code (where I'll remove the bits that are now
duplicated in the near future).  This stuff should be useful in its
own right for the majority of the i386 targets, but I hope to make use
of it for fixing a regression that surfaced in an attempt to make the
i386 target use the generic call dummy stuff.

Committed.

Mark


Index: ChangeLog
from  Mark Kettenis  <kettenis@gnu.org>

	* i386-tdep.c (i386_frameless_signal_p): New function.
	(i386_frame_chain): Deal with frameless signals.
	(i386_sigtramp_saved_sp): New function.
	(i386_frame_saved_pc): Deal with frameless signals.
	(i386_saved_pc_after_call): Make sure the correct value is
	returned just after entry into a sigtramp.
	* i386bsd-tdep.c (i386bsd_sc_sp_offset, i386nbsd_sc_sp_offset,
	i386fbsd4_sc_sp_offset): New variables.
	(i386bsd_init_abi, i386nbsd_init_abi, i386fbsd4_init_abi): Use
	these variables to initialize tdep->sc_sp_offset.  * i386bsd-nat.c
	(_initialize_i386bsd_nat): Add sanity check for sc_sp_offset
	similiar to what we already did for sc_pc_offset.
	* i386-sol2-tdep.c (i386_sol2_init_abi): Initialize
	tdep->sc_sp_offset.

Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.68
diff -u -p -r1.68 i386-tdep.c
--- i386-tdep.c 1 Jul 2002 21:16:32 -0000 1.68
+++ i386-tdep.c 2 Jul 2002 08:59:04 -0000
@@ -452,6 +452,38 @@ i386_get_frame_setup (CORE_ADDR pc)
   return (-1);
 }
 
+/* Signal trampolines don't have a meaningful frame.  The frame
+   pointer value we use is actually the frame pointer of the calling
+   frame -- that is, the frame which was in progress when the signal
+   trampoline was entered.  GDB mostly treats this frame pointer value
+   as a magic cookie.  We detect the case of a signal trampoline by
+   looking at the SIGNAL_HANDLER_CALLER field, which is set based on
+   PC_IN_SIGTRAMP.
+
+   When a signal trampoline is invoked from a frameless function, we
+   essentially have two frameless functions in a row.  In this case,
+   we use the same magic cookie for three frames in a row.  We detect
+   this case by seeing whether the next frame has
+   SIGNAL_HANDLER_CALLER set, and, if it does, checking whether the
+   current frame is actually frameless.  In this case, we need to get
+   the PC by looking at the SP register value stored in the signal
+   context.
+
+   This should work in most cases except in horrible situations where
+   a signal occurs just as we enter a function but before the frame
+   has been set up.  */
+
+/* Return non-zero if we're dealing with a frameless signal, that is,
+   a signal trampoline invoked from a frameless function.  */
+
+static int
+i386_frameless_signal_p (struct frame_info *frame)
+{
+  return (frame->next
+	  && frame->next->signal_handler_caller
+	  && frameless_look_for_prologue);
+}
+
 /* Return the chain-pointer for FRAME.  In the case of the i386, the
    frame's nominal address is the address of a 4-byte word containing
    the calling frame's address.  */
@@ -459,7 +491,8 @@ i386_get_frame_setup (CORE_ADDR pc)
 static CORE_ADDR
 i386_frame_chain (struct frame_info *frame)
 {
-  if (frame->signal_handler_caller)
+  if (frame->signal_handler_caller
+      || i386_frameless_signal_p (frame))
     return frame->frame;
 
   if (! inside_entry_file (frame->pc))
@@ -494,6 +527,19 @@ i386_sigtramp_saved_pc (struct frame_inf
   return read_memory_unsigned_integer (addr + tdep->sc_pc_offset, 4);
 }
 
+/* Assuming FRAME is for a sigtramp routine, return the saved stack
+   pointer.  */
+
+static CORE_ADDR
+i386_sigtramp_saved_sp (struct frame_info *frame)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  CORE_ADDR addr;
+
+  addr = tdep->sigcontext_addr (frame);
+  return read_memory_unsigned_integer (addr + tdep->sc_sp_offset, 4);
+}
+
 /* Return the saved program counter for FRAME.  */
 
 static CORE_ADDR
@@ -502,6 +548,12 @@ i386_frame_saved_pc (struct frame_info *
   if (frame->signal_handler_caller)
     return i386_sigtramp_saved_pc (frame);
 
+  if (i386_frameless_signal_p (frame))
+    {
+      CORE_ADDR sp = i386_sigtramp_saved_sp (frame->next);
+      return read_memory_unsigned_integer (sp, 4);
+    }
+
   return read_memory_unsigned_integer (frame->frame + 4, 4);
 }
 
@@ -510,6 +562,9 @@ i386_frame_saved_pc (struct frame_info *
 static CORE_ADDR
 i386_saved_pc_after_call (struct frame_info *frame)
 {
+  if (frame->signal_handler_caller)
+    return i386_sigtramp_saved_pc (frame);
+
   return read_memory_unsigned_integer (read_register (SP_REGNUM), 4);
 }
 
Index: i386bsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386bsd-tdep.c,v
retrieving revision 1.5
diff -u -p -r1.5 i386bsd-tdep.c
--- i386bsd-tdep.c 1 Jul 2002 21:16:32 -0000 1.5
+++ i386bsd-tdep.c 2 Jul 2002 08:59:04 -0000
@@ -89,6 +89,7 @@ i386bsd_aout_in_solib_call_trampoline (C
 
 /* From <machine/signal.h>.  */
 int i386bsd_sc_pc_offset = 20;
+int i386bsd_sc_sp_offset = 8;
 
 static void
 i386bsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -107,12 +108,14 @@ i386bsd_init_abi (struct gdbarch_info in
   tdep->sigtramp_end = 0xfdbfe000;
   tdep->sigcontext_addr = i386bsd_sigcontext_addr;
   tdep->sc_pc_offset = i386bsd_sc_pc_offset;
+  tdep->sc_sp_offset = i386bsd_sc_sp_offset;
 }
 
 /* NetBSD 1.0 or later.  */
 
 /* From <machine/signal.h>.  */
 int i386nbsd_sc_pc_offset = 44;
+int i386nbsd_sc_sp_offset = 56;
 
 static void
 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -132,6 +135,7 @@ i386nbsd_init_abi (struct gdbarch_info i
   /* NetBSD has a `struct sigcontext' that's different from the
      origional 4.3 BSD.  */
   tdep->sc_pc_offset = i386nbsd_sc_pc_offset;
+  tdep->sc_sp_offset = i386nbsd_sc_sp_offset;
 }
 
 /* NetBSD ELF.  */
@@ -198,6 +202,7 @@ i386fbsd_init_abi (struct gdbarch_info i
 
 /* From <machine/signal.h>.  */
 int i386fbsd4_sc_pc_offset = 76;
+int i386fbsd4_sc_sp_offset = 88;
 
 static void
 i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -210,6 +215,7 @@ i386fbsd4_init_abi (struct gdbarch_info 
 
   /* FreeBSD 4.0 introduced a new `struct sigcontext'.  */
   tdep->sc_pc_offset = i386fbsd4_sc_pc_offset;
+  tdep->sc_sp_offset = i386fbsd4_sc_sp_offset;
 }
 
 
Index: i386bsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386bsd-nat.c,v
retrieving revision 1.15
diff -u -p -r1.15 i386bsd-nat.c
--- i386bsd-nat.c 30 Jun 2002 17:01:42 -0000 1.15
+++ i386bsd-nat.c 2 Jul 2002 08:59:04 -0000
@@ -387,6 +387,7 @@ void
 _initialize_i386bsd_nat (void)
 {
   int sc_pc_offset;
+  int sc_sp_offset;
 
   /* To support the recognition of signal handlers, i386bsd-tdep.c
      hardcodes some constants.  Inclusion of this file means that we
@@ -396,13 +397,19 @@ _initialize_i386bsd_nat (void)
 
 #if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
   extern int i386fbsd4_sc_pc_offset;
+  extern int i386fbsd4_sc_sp_offset;
 #define SC_PC_OFFSET i386fbsd4_sc_pc_offset
+#define SC_SP_OFFSET i386fbsd4_sc_sp_offset
 #elif defined (NetBSD) || defined (__NetBSD_Version__) || defined (OpenBSD)
   extern int i386nbsd_sc_pc_offset;
+  extern int i386nbsd_sc_sp_offset;
 #define SC_PC_OFFSET i386nbsd_sc_pc_offset
+#define SC_SP_OFFSET i386nbsd_sc_sp_offset
 #else
   extern int i386bsd_sc_pc_offset;
+  extern int i386bsd_sc_sp_offset;
 #define SC_PC_OFFSET i386bsd_sc_pc_offset
+#define SC_SP_OFFSET i386bsd_sc_sp_offset
 #endif
 
   /* Override the default value for the offset of the program counter
@@ -418,4 +425,17 @@ Please report this to <bug-gdb@gnu.org>.
     }
 
   SC_PC_OFFSET = sc_pc_offset;
+
+  /* Likewise for the stack pointer.  */
+  sc_sp_offset = offsetof (struct sigcontext, sc_sp);
+
+  if (SC_SP_OFFSET != sc_sp_offset)
+    {
+      warning ("\
+offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
+Please report this to <bug-gdb@gnu.org>.",
+	       sc_sp_offset, SC_SP_OFFSET);
+    }
+
+  SC_SP_OFFSET = sc_sp_offset;
 }
Index: i386-sol2-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-sol2-tdep.c,v
retrieving revision 1.4
diff -u -p -r1.4 i386-sol2-tdep.c
--- i386-sol2-tdep.c 1 Jul 2002 21:16:32 -0000 1.4
+++ i386-sol2-tdep.c 2 Jul 2002 08:59:04 -0000
@@ -46,6 +46,7 @@ i386_sol2_init_abi (struct gdbarch_info 
   set_gdbarch_pc_in_sigtramp (gdbarch, i386_sol2_pc_in_sigtramp);
   tdep->sigcontext_addr = i386bsd_sigcontext_addr;
   tdep->sc_pc_offset = 36 + 14 * 4;
+  tdep->sc_sp_offset = 36 + 7 * 4;
 
   /* Assume that the prototype flag can be trusted.  */
   set_gdbarch_coerce_float_to_double (gdbarch,


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