aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog15
-rw-r--r--gdb/i386-sol2-tdep.c1
-rw-r--r--gdb/i386-tdep.c57
-rw-r--r--gdb/i386bsd-nat.c20
-rw-r--r--gdb/i386bsd-tdep.c6
5 files changed, 98 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 894e8ff..81c1a00 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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>
diff --git a/gdb/i386-sol2-tdep.c b/gdb/i386-sol2-tdep.c
index 84257ee..023e446 100644
--- a/gdb/i386-sol2-tdep.c
+++ b/gdb/i386-sol2-tdep.c
@@ -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,
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index c45c271..5940146 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -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);
}
diff --git a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c
index 382e3f3..8a3acd4 100644
--- a/gdb/i386bsd-nat.c
+++ b/gdb/i386bsd-nat.c
@@ -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;
}
diff --git a/gdb/i386bsd-tdep.c b/gdb/i386bsd-tdep.c
index a419cab..61213ff 100644
--- a/gdb/i386bsd-tdep.c
+++ b/gdb/i386bsd-tdep.c
@@ -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;
}