(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.
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>
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,
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. */
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))
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
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);
}
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);
}
_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
#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
}
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;
}
/* 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)
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)
/* 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. */
/* 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)
/* 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