diff options
author | Mark Kettenis <kettenis@gnu.org> | 2002-07-02 09:12:37 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2002-07-02 09:12:37 +0000 |
commit | fc110bcbcdeceb2b2a6ece71508a22a34ea96ef6 (patch) | |
tree | 83c9856277cbc2b6edb883020205e9bf7231972f /gdb/i386-tdep.c | |
parent | 1e2e82366b542a3fd0429aa8795fb8172e73d6e6 (diff) | |
download | gdb-fc110bcbcdeceb2b2a6ece71508a22a34ea96ef6.tar.gz |
* 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.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index c45c2712dc7..59401467da4 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); } |