This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[PATCH] Add support for "frameless" signals for all i386 targets
- From: Mark Kettenis <kettenis at gnu dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Tue, 2 Jul 2002 11:04:57 +0200 (CEST)
- Subject: [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,