aboutsummaryrefslogtreecommitdiff
path: root/gdb/config/i386/tm-linux.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/config/i386/tm-linux.h')
-rw-r--r--gdb/config/i386/tm-linux.h72
1 files changed, 70 insertions, 2 deletions
diff --git a/gdb/config/i386/tm-linux.h b/gdb/config/i386/tm-linux.h
index e39dc04..0767bd9 100644
--- a/gdb/config/i386/tm-linux.h
+++ b/gdb/config/i386/tm-linux.h
@@ -26,8 +26,14 @@
#include "i386/tm-i386.h"
-/* Offset to saved PC in sigcontext, from <linux/signal.h>. */
-#define SIGCONTEXT_PC_OFFSET 38
+/* Size of sigcontext, from <asm/sigcontext.h>. */
+#define LINUX_SIGCONTEXT_SIZE (88)
+
+/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
+#define LINUX_SIGCONTEXT_PC_OFFSET (56)
+
+/* Offset to saved SP in sigcontext, from <asm/sigcontext.h>. */
+#define LINUX_SIGCONTEXT_SP_OFFSET (28)
/* We need this file for the SOLIB_TRAMPOLINE stuff. */
@@ -36,4 +42,66 @@
/* The following works around a problem with /usr/include/sys/procfs.h */
#define sys_quotactl 1
+/* When the i386 Linux kernel calls a signal handler, the return
+ address points to a bit of code on the stack. These definitions
+ are used to identify this bit of code as a signal trampoline in
+ order to support backtracing through calls to signal handlers. */
+
+#define I386_LINUX_SIGTRAMP
+#define IN_SIGTRAMP(pc, name) ((name) == NULL && i386_linux_sigtramp (pc))
+
+extern int i386_linux_sigtramp PARAMS ((CORE_ADDR));
+
+/* We need our own version of sigtramp_saved_pc to get the saved PC in
+ a sigtramp routine. */
+
+#define sigtramp_saved_pc i386_linux_sigtramp_saved_pc
+extern CORE_ADDR i386_linux_sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+/* Signal trampolines don't have a meaningful frame. As in 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))
+
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(FRAME) \
+ ((FRAME)->signal_handler_caller \
+ ? (FRAME)->frame \
+ : (FRAMELESS_SIGNAL (FRAME) \
+ ? (FRAME)->frame \
+ : (!inside_entry_file ((FRAME)->pc) \
+ ? read_memory_integer ((FRAME)->frame, 4) \
+ : 0)))
+
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) \
+ ((FRAME)->signal_handler_caller \
+ ? sigtramp_saved_pc (FRAME) \
+ : (FRAMELESS_SIGNAL (FRAME) \
+ ? read_memory_integer (i386_linux_sigtramp_saved_sp ((FRAME)->next), 4) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)))
+
+extern CORE_ADDR i386_linux_sigtramp_saved_sp PARAMS ((struct frame_info *));
+
#endif /* #ifndef TM_LINUX_H */