* 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.
This commit is contained in:
Mark Kettenis 2002-07-02 09:12:37 +00:00
parent 99881371eb
commit 6bff26defb
5 changed files with 98 additions and 1 deletions

View File

@ -1,5 +1,20 @@
2002-07-02 Mark Kettenis <kettenis@gnu.org>
* 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 <mludvig@suse.cz>

View File

@ -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,

View File

@ -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);
}

View File

@ -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 <bug-gdb@gnu.org>.",
}
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 <bug-gdb@gnu.org>.",
sc_sp_offset, SC_SP_OFFSET);
}
SC_SP_OFFSET = sc_sp_offset;
}

View File

@ -89,6 +89,7 @@ i386bsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name)
/* From <machine/signal.h>. */
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 <machine/signal.h>. */
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 <machine/signal.h>. */
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;
}