* i386-tdep.c (i386_frameless_signal_p): New function.
authorMark Kettenis <kettenis@gnu.org>
Tue, 2 Jul 2002 09:12:37 +0000 (09:12 +0000)
committerMark Kettenis <kettenis@gnu.org>
Tue, 2 Jul 2002 09:12:37 +0000 (09:12 +0000)
(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.

gdb/ChangeLog
gdb/i386-sol2-tdep.c
gdb/i386-tdep.c
gdb/i386bsd-nat.c
gdb/i386bsd-tdep.c

index 894e8ff..81c1a00 100644 (file)
@@ -1,5 +1,20 @@
 2002-07-02  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.
+
        * i386nbsd-tdep.c (fetch_elfcore_registers): Wrap long line.
 
 2002-07-02  Michal Ludvig  <mludvig@suse.cz>
index 84257ee..023e446 100644 (file)
@@ -46,6 +46,7 @@ i386_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   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 c45c271..5940146 100644 (file)
@@ -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_info *frame)
   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 *frame)
   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 *frame)
 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 382e3f3..8a3acd4 100644 (file)
@@ -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 a419cab..61213ff 100644 (file)
@@ -89,6 +89,7 @@ i386bsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name)
 
 /* 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 info, struct gdbarch *gdbarch)
   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 info, struct gdbarch *gdbarch)
   /* 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 info, struct gdbarch *gdbarch)
 
 /* 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 info, struct gdbarch *gdbarch)
 
   /* FreeBSD 4.0 introduced a new `struct sigcontext'.  */
   tdep->sc_pc_offset = i386fbsd4_sc_pc_offset;
+  tdep->sc_sp_offset = i386fbsd4_sc_sp_offset;
 }
 
 \f