* 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:
parent
2b8a5373e1
commit
848cfffbc5
@ -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>
|
||||
|
||||
* sh-tdep.c (sh_nofp_frame_init_saved_regs): Fix error in
|
||||
|
152
gdb/arm-tdep.c
152
gdb/arm-tdep.c
@ -421,6 +421,11 @@ arm_skip_prologue (CORE_ADDR pc)
|
||||
char *func_name;
|
||||
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. */
|
||||
|
||||
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 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))
|
||||
{
|
||||
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
|
||||
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)
|
||||
|
||||
#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))
|
||||
return generic_read_register_dummy (fi->pc, fi->frame, regnum);
|
||||
else
|
||||
#endif
|
||||
if (fi->saved_regs[regnum] != 0)
|
||||
return read_memory_integer (fi->saved_regs[regnum],
|
||||
REGISTER_RAW_SIZE (regnum));
|
||||
{
|
||||
if (USE_GENERIC_DUMMY_FRAMES
|
||||
&& PC_IN_CALL_DUMMY (fi->pc, 0, 0))
|
||||
{
|
||||
return generic_read_register_dummy (fi->pc, fi->frame, regnum);
|
||||
}
|
||||
else 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],
|
||||
REGISTER_RAW_SIZE (regnum));
|
||||
}
|
||||
}
|
||||
return read_register (regnum);
|
||||
}
|
||||
/* 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
|
||||
arm_frame_chain (struct frame_info *fi)
|
||||
{
|
||||
#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
|
||||
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;
|
||||
CORE_ADDR caller_pc;
|
||||
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)
|
||||
return 0;
|
||||
|
||||
/* If the caller is the startup code, we're at the end of the chain. */
|
||||
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,
|
||||
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);
|
||||
|
||||
#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
|
||||
the sigtramp and call dummy cases. */
|
||||
if (!fi->next)
|
||||
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
|
||||
sp = (fi->next->frame - fi->next->extra_info->frameoffset
|
||||
+ fi->next->extra_info->framesize);
|
||||
@ -1188,6 +1187,11 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
|
||||
if (!fi->next)
|
||||
/* This is the innermost frame? */
|
||||
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
|
||||
|| 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
|
||||
arm_frame_saved_pc (struct frame_info *fi)
|
||||
{
|
||||
#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))
|
||||
/* If a dummy frame, pull the PC out of the frame's register buffer. */
|
||||
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);
|
||||
else
|
||||
#endif
|
||||
|
||||
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame - fi->extra_info->frameoffset,
|
||||
fi->frame))
|
||||
{
|
||||
@ -1270,6 +1274,16 @@ arm_frame_init_saved_regs (struct frame_info *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. */
|
||||
|
||||
static void
|
||||
@ -1524,6 +1538,14 @@ arm_pop_frame (void)
|
||||
CORE_ADDR old_SP = (frame->frame - frame->extra_info->frameoffset
|
||||
+ 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++)
|
||||
if (frame->saved_regs[regnum] != 0)
|
||||
write_register (regnum,
|
||||
@ -2893,6 +2915,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
tdep->lowest_pc = 0x20;
|
||||
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);
|
||||
|
||||
/* 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_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_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_args_skip (gdbarch, 0);
|
||||
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);
|
||||
#else
|
||||
set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
|
||||
#endif
|
||||
set_gdbarch_pop_frame (gdbarch, arm_pop_frame);
|
||||
|
||||
/* Address manipulation. */
|
||||
|
Loading…
Reference in New Issue
Block a user