* arm-tdep.c (arm_skip_prologue): Handle generic dummy frames.

(thumb_scan_prologue): Ditto.
(arm_find_callers_reg): Ditto.
(arm_frame_chain): Ditto.
(arm_init_extra_frame_info): Ditto.
(arm_frame_saved_pc): Ditto.
(arm_pop_frame): Ditto.
(arm_push_return_address): New function.
(arm_gdbarch_init): Initialize use_generic_dummy_frames,
call_dummy_location, call_dummy_breakpoint_offset_p,
call_dummy_breakpoint_offset, call_dummy_p,
call_dummy_stack_adjust_p, call_dummy_words,
sizeof_call_dummy_words, call_dummy_start_offset,
call_dummy_length, fix_call_dummy, pc_in_call_dummy,
call_dummy_address, push_return_address and push_dummy_frame for
generic dummy frames.
This commit is contained in:
Andrew Cagney 2002-05-08 01:35:51 +00:00
parent 2b8a5373e1
commit 848cfffbc5
2 changed files with 123 additions and 48 deletions

View File

@ -1,3 +1,22 @@
2002-05-07 Andrew Cagney <ac131313@redhat.com>
* arm-tdep.c (arm_skip_prologue): Handle generic dummy frames.
(thumb_scan_prologue): Ditto.
(arm_find_callers_reg): Ditto.
(arm_frame_chain): Ditto.
(arm_init_extra_frame_info): Ditto.
(arm_frame_saved_pc): Ditto.
(arm_pop_frame): Ditto.
(arm_push_return_address): New function.
(arm_gdbarch_init): Initialize use_generic_dummy_frames,
call_dummy_location, call_dummy_breakpoint_offset_p,
call_dummy_breakpoint_offset, call_dummy_p,
call_dummy_stack_adjust_p, call_dummy_words,
sizeof_call_dummy_words, call_dummy_start_offset,
call_dummy_length, fix_call_dummy, pc_in_call_dummy,
call_dummy_address, push_return_address and push_dummy_frame for
generic dummy frames.
2002-05-07 Jason Thorpe <thorpej@wasabisystems.com> 2002-05-07 Jason Thorpe <thorpej@wasabisystems.com>
* sh-tdep.c (sh_nofp_frame_init_saved_regs): Fix error in * sh-tdep.c (sh_nofp_frame_init_saved_regs): Fix error in

View File

@ -421,6 +421,11 @@ arm_skip_prologue (CORE_ADDR pc)
char *func_name; char *func_name;
struct symtab_and_line sal; struct symtab_and_line sal;
/* If we're in a dummy frame, don't even try to skip the prologue. */
if (USE_GENERIC_DUMMY_FRAMES
&& PC_IN_CALL_DUMMY (pc, 0, 0))
return pc;
/* See what the symbol table says. */ /* See what the symbol table says. */
if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end)) if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
@ -553,6 +558,12 @@ thumb_scan_prologue (struct frame_info *fi)
int findmask = 0; int findmask = 0;
int i; int i;
/* Don't try to scan dummy frames. */
if (USE_GENERIC_DUMMY_FRAMES
&& fi != NULL
&& PC_IN_CALL_DUMMY (fi->pc, 0, 0))
return;
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end)) if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
{ {
struct symtab_and_line sal = find_pc_line (prologue_start, 0); struct symtab_and_line sal = find_pc_line (prologue_start, 0);
@ -990,16 +1001,27 @@ arm_scan_prologue (struct frame_info *fi)
static CORE_ADDR static CORE_ADDR
arm_find_callers_reg (struct frame_info *fi, int regnum) arm_find_callers_reg (struct frame_info *fi, int regnum)
{ {
/* NOTE: cagney/2002-05-03: This function really shouldn't be
needed. Instead the (still being written) register unwind
function could be called directly. */
for (; fi; fi = fi->next) for (; fi; fi = fi->next)
{
#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */ if (USE_GENERIC_DUMMY_FRAMES
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) && PC_IN_CALL_DUMMY (fi->pc, 0, 0))
{
return generic_read_register_dummy (fi->pc, fi->frame, regnum); return generic_read_register_dummy (fi->pc, fi->frame, regnum);
else }
#endif else if (fi->saved_regs[regnum] != 0)
if (fi->saved_regs[regnum] != 0) {
/* NOTE: cagney/2002-05-03: This would normally need to
handle ARM_SP_REGNUM as a special case as, according to
the frame.h comments, saved_regs[SP_REGNUM] contains the
SP value not its address. It appears that the ARM isn't
doing this though. */
return read_memory_integer (fi->saved_regs[regnum], return read_memory_integer (fi->saved_regs[regnum],
REGISTER_RAW_SIZE (regnum)); REGISTER_RAW_SIZE (regnum));
}
}
return read_register (regnum); return read_register (regnum);
} }
/* Function: frame_chain Given a GDB frame, determine the address of /* Function: frame_chain Given a GDB frame, determine the address of
@ -1011,34 +1033,19 @@ arm_find_callers_reg (struct frame_info *fi, int regnum)
static CORE_ADDR static CORE_ADDR
arm_frame_chain (struct frame_info *fi) arm_frame_chain (struct frame_info *fi)
{ {
#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */ CORE_ADDR caller_pc;
CORE_ADDR fn_start, callers_pc, fp;
/* Is this a dummy frame? */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return fi->frame; /* dummy frame same as caller's frame */
/* Is caller-of-this a dummy frame? */
callers_pc = FRAME_SAVED_PC (fi); /* find out who called us: */
fp = arm_find_callers_reg (fi, ARM_FP_REGNUM);
if (PC_IN_CALL_DUMMY (callers_pc, fp, fp))
return fp; /* dummy frame's frame may bear no relation to ours */
if (find_pc_partial_function (fi->pc, 0, &fn_start, 0))
if (fn_start == entry_point_address ())
return 0; /* in _start fn, don't chain further */
#endif
CORE_ADDR caller_pc, fn_start;
int framereg = fi->extra_info->framereg; int framereg = fi->extra_info->framereg;
if (USE_GENERIC_DUMMY_FRAMES
&& PC_IN_CALL_DUMMY (fi->pc, 0, 0))
/* A generic call dummy's frame is the same as caller's. */
return fi->frame;
if (fi->pc < LOWEST_PC) if (fi->pc < LOWEST_PC)
return 0; return 0;
/* If the caller is the startup code, we're at the end of the chain. */ /* If the caller is the startup code, we're at the end of the chain. */
caller_pc = FRAME_SAVED_PC (fi); caller_pc = FRAME_SAVED_PC (fi);
if (find_pc_partial_function (caller_pc, 0, &fn_start, 0))
if (fn_start == entry_point_address ())
return 0;
/* If the caller is Thumb and the caller is ARM, or vice versa, /* If the caller is Thumb and the caller is ARM, or vice versa,
the frame register of the caller is different from ours. the frame register of the caller is different from ours.
@ -1109,24 +1116,16 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
memset (fi->saved_regs, '\000', sizeof fi->saved_regs); memset (fi->saved_regs, '\000', sizeof fi->saved_regs);
#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
/* We need to setup fi->frame here because run_stack_dummy gets
it wrong by assuming it's always FP. */
fi->frame = generic_read_register_dummy (fi->pc, fi->frame,
ARM_SP_REGNUM);
fi->extra_info->framesize = 0;
fi->extra_info->frameoffset = 0;
return;
}
else
#endif
/* Compute stack pointer for this frame. We use this value for both /* Compute stack pointer for this frame. We use this value for both
the sigtramp and call dummy cases. */ the sigtramp and call dummy cases. */
if (!fi->next) if (!fi->next)
sp = read_sp(); sp = read_sp();
else if (USE_GENERIC_DUMMY_FRAMES
&& PC_IN_CALL_DUMMY (fi->next->pc, 0, 0))
/* For generic dummy frames, pull the value direct from the frame.
Having an unwind function to do this would be nice. */
sp = generic_read_register_dummy (fi->next->pc, fi->next->frame,
ARM_SP_REGNUM);
else else
sp = (fi->next->frame - fi->next->extra_info->frameoffset sp = (fi->next->frame - fi->next->extra_info->frameoffset
+ fi->next->extra_info->framesize); + fi->next->extra_info->framesize);
@ -1188,6 +1187,11 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
if (!fi->next) if (!fi->next)
/* This is the innermost frame? */ /* This is the innermost frame? */
fi->frame = read_register (fi->extra_info->framereg); fi->frame = read_register (fi->extra_info->framereg);
else if (USE_GENERIC_DUMMY_FRAMES
&& PC_IN_CALL_DUMMY (fi->next->pc, 0, 0))
/* Next inner most frame is a dummy, just grab its frame.
Dummy frames always have the same FP as their caller. */
fi->frame = fi->next->frame;
else if (fi->extra_info->framereg == ARM_FP_REGNUM else if (fi->extra_info->framereg == ARM_FP_REGNUM
|| fi->extra_info->framereg == THUMB_FP_REGNUM) || fi->extra_info->framereg == THUMB_FP_REGNUM)
{ {
@ -1224,11 +1228,11 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
static CORE_ADDR static CORE_ADDR
arm_frame_saved_pc (struct frame_info *fi) arm_frame_saved_pc (struct frame_info *fi)
{ {
#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */ /* If a dummy frame, pull the PC out of the frame's register buffer. */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) if (USE_GENERIC_DUMMY_FRAMES
&& PC_IN_CALL_DUMMY (fi->pc, 0, 0))
return generic_read_register_dummy (fi->pc, fi->frame, ARM_PC_REGNUM); return generic_read_register_dummy (fi->pc, fi->frame, ARM_PC_REGNUM);
else
#endif
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame - fi->extra_info->frameoffset, if (PC_IN_CALL_DUMMY (fi->pc, fi->frame - fi->extra_info->frameoffset,
fi->frame)) fi->frame))
{ {
@ -1270,6 +1274,16 @@ arm_frame_init_saved_regs (struct frame_info *fip)
arm_init_extra_frame_info (0, fip); arm_init_extra_frame_info (0, fip);
} }
/* Set the return address for a generic dummy frame. ARM uses the
entry point. */
static CORE_ADDR
arm_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
write_register (ARM_LR_REGNUM, CALL_DUMMY_ADDRESS ());
return sp;
}
/* Push an empty stack frame, to record the current PC, etc. */ /* Push an empty stack frame, to record the current PC, etc. */
static void static void
@ -1524,6 +1538,14 @@ arm_pop_frame (void)
CORE_ADDR old_SP = (frame->frame - frame->extra_info->frameoffset CORE_ADDR old_SP = (frame->frame - frame->extra_info->frameoffset
+ frame->extra_info->framesize); + frame->extra_info->framesize);
if (USE_GENERIC_DUMMY_FRAMES
&& PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
{
generic_pop_dummy_frame ();
flush_cached_frames ();
return;
}
for (regnum = 0; regnum < NUM_REGS; regnum++) for (regnum = 0; regnum < NUM_REGS; regnum++)
if (frame->saved_regs[regnum] != 0) if (frame->saved_regs[regnum] != 0)
write_register (regnum, write_register (regnum,
@ -2893,6 +2915,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->lowest_pc = 0x20; tdep->lowest_pc = 0x20;
tdep->jb_pc = -1; /* Longjump support not enabled by default. */ tdep->jb_pc = -1; /* Longjump support not enabled by default. */
#if OLD_STYLE_ARM_DUMMY_FRAMES
/* NOTE: cagney/2002-05-07: Enable the below to restore the old ARM
specific (non-generic) dummy frame code. Might be useful if
there appears to be a problem with the generic dummy frame
mechanism that replaced it. */
set_gdbarch_use_generic_dummy_frames (gdbarch, 0); set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
/* Call dummy code. */ /* Call dummy code. */
@ -2912,6 +2939,27 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_fix_call_dummy (gdbarch, arm_fix_call_dummy); set_gdbarch_fix_call_dummy (gdbarch, arm_fix_call_dummy);
set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack); set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
#else
set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_p (gdbarch, 1);
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
set_gdbarch_call_dummy_words (gdbarch, arm_call_dummy_words);
set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
set_gdbarch_call_dummy_start_offset (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);
set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
set_gdbarch_push_return_address (gdbarch, arm_push_return_address);
#endif
set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register); set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
set_gdbarch_push_arguments (gdbarch, arm_push_arguments); set_gdbarch_push_arguments (gdbarch, arm_push_arguments);
@ -2931,7 +2979,15 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_frame_num_args (gdbarch, arm_frame_num_args); set_gdbarch_frame_num_args (gdbarch, arm_frame_num_args);
set_gdbarch_frame_args_skip (gdbarch, 0); set_gdbarch_frame_args_skip (gdbarch, 0);
set_gdbarch_frame_init_saved_regs (gdbarch, arm_frame_init_saved_regs); set_gdbarch_frame_init_saved_regs (gdbarch, arm_frame_init_saved_regs);
#if OLD_STYLE_ARM_DUMMY_FRAMES
/* NOTE: cagney/2002-05-07: Enable the below to restore the old ARM
specific (non-generic) dummy frame code. Might be useful if
there appears to be a problem with the generic dummy frame
mechanism that replaced it. */
set_gdbarch_push_dummy_frame (gdbarch, arm_push_dummy_frame); set_gdbarch_push_dummy_frame (gdbarch, arm_push_dummy_frame);
#else
set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
#endif
set_gdbarch_pop_frame (gdbarch, arm_pop_frame); set_gdbarch_pop_frame (gdbarch, arm_pop_frame);
/* Address manipulation. */ /* Address manipulation. */