aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2002-05-08 01:35:51 +0000
committerAndrew Cagney <cagney@redhat.com>2002-05-08 01:35:51 +0000
commit848cfffbc5089b1711fe84eafa1c30ca6baf6d6f (patch)
tree71692d2a4a4dff145ad84912189a4227824176d1 /gdb/arm-tdep.c
parent2b8a5373e1ce837912558a50ed78b9bd3894a388 (diff)
downloadfsf-binutils-gdb-848cfffbc5089b1711fe84eafa1c30ca6baf6d6f.zip
fsf-binutils-gdb-848cfffbc5089b1711fe84eafa1c30ca6baf6d6f.tar.gz
fsf-binutils-gdb-848cfffbc5089b1711fe84eafa1c30ca6baf6d6f.tar.bz2
* 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.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c152
1 files changed, 104 insertions, 48 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 2ea4d28..bc928e12 100644
--- a/gdb/arm-tdep.c
+++ b/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. */