aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-tdep.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2002-07-02 09:12:37 +0000
committerMark Kettenis <kettenis@gnu.org>2002-07-02 09:12:37 +0000
commit6bff26defb5723704ec856ed739f8e733a443a00 (patch)
tree237285373f990257618aa7877436e5bb1420cdc5 /gdb/i386-tdep.c
parent99881371eb4a78527f3e00841833eca312f218a7 (diff)
downloadgdb-6bff26defb5723704ec856ed739f8e733a443a00.zip
gdb-6bff26defb5723704ec856ed739f8e733a443a00.tar.gz
gdb-6bff26defb5723704ec856ed739f8e733a443a00.tar.bz2
* 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.
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r--gdb/i386-tdep.c57
1 files changed, 56 insertions, 1 deletions
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);
}