From 6bff26defb5723704ec856ed739f8e733a443a00 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Tue, 2 Jul 2002 09:12:37 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 15 ++++++++++++ gdb/i386-sol2-tdep.c | 1 + gdb/i386-tdep.c | 57 +++++++++++++++++++++++++++++++++++++++++++- gdb/i386bsd-nat.c | 20 ++++++++++++++++ gdb/i386bsd-tdep.c | 6 +++++ 5 files changed, 98 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 894e8ff6fe..81c1a004c6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,20 @@ 2002-07-02 Mark Kettenis + * 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 diff --git a/gdb/i386-sol2-tdep.c b/gdb/i386-sol2-tdep.c index 84257ee0b4..023e446fa8 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 c45c2712dc..59401467da 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 382e3f3f8b..8a3acd4cf5 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 .", } 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 .", + 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 a419cab87d..61213ff658 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 . */ 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 . */ 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 . */ 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; }