diff options
author | Mark Kettenis <kettenis@gnu.org> | 2001-03-28 11:36:23 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2001-03-28 11:36:23 +0000 |
commit | 9c910f2f54d9671b100bc9ce9698d283c1bc214c (patch) | |
tree | 930dbfb17fbbbc422cff5cd71a868cd65907dc49 /gdb/i386-linux-tdep.c | |
parent | 0dcb8b8253b3ae6763937bcb59473e510793af30 (diff) | |
download | gdb-9c910f2f54d9671b100bc9ce9698d283c1bc214c.tar.gz |
* i386-linux-tdep.c (FRAMELESS_SIGNAL): Moved here from
config/i386/nm-linux.h (including comment).
(i386_linux_frame_chain): New function implementing guts of the
former FRAME_CHAIN macro, but using read_memory_unsigned_integer
instead of read_memory_integer.
(i386_linux_frame_saved_pc): Removed doc pointing to
i386/tm-linux.h for an explanation of FRAMELESS_SIGNAL since that
now lives in this file.
* config/i386/tm-linux.h (FRAMELESS_SIGNAL): Moved to
i386-linux-tdep.c (including comment).
(FRAME_CHAIN): Redefined in terms of i386_linux_frame_chain.
(i386_linux_frame_chain): New prototype.
Diffstat (limited to 'gdb/i386-linux-tdep.c')
-rw-r--r-- | gdb/i386-linux-tdep.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index 56a5eadecd9..f98801b4d0c 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -277,6 +277,44 @@ i386_linux_sigtramp_saved_sp (struct frame_info *frame) return read_memory_integer (addr + LINUX_SIGCONTEXT_SP_OFFSET, 4); } +/* Signal trampolines don't have a meaningful frame. As in + "i386/tm-i386.h", 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 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. */ + +#define FRAMELESS_SIGNAL(frame) \ + ((frame)->next != NULL \ + && (frame)->next->signal_handler_caller \ + && frameless_look_for_prologue (frame)) + +CORE_ADDR +i386_linux_frame_chain (struct frame_info *frame) +{ + if (frame->signal_handler_caller || FRAMELESS_SIGNAL (frame)) + return frame->frame; + + if (! inside_entry_file (frame->pc)) + return read_memory_unsigned_integer (frame->frame, 4); + + return 0; +} + /* Return the saved program counter for FRAME. */ CORE_ADDR @@ -285,11 +323,6 @@ i386_linux_frame_saved_pc (struct frame_info *frame) if (frame->signal_handler_caller) return i386_linux_sigtramp_saved_pc (frame); - /* See comment in "i386/tm-linux.h" for an explanation what this - "FRAMELESS_SIGNAL" stuff is supposed to do. - - FIXME: kettenis/2001-03-26: That comment should eventually be - moved to this file. */ if (FRAMELESS_SIGNAL (frame)) { CORE_ADDR sp = i386_linux_sigtramp_saved_sp (frame->next); @@ -309,7 +342,6 @@ i386_linux_saved_pc_after_call (struct frame_info *frame) return read_memory_integer (read_register (SP_REGNUM), 4); } - /* Calling functions in shared libraries. */ |