diff options
author | Andrew Cagney <cagney@redhat.com> | 2002-05-08 01:35:51 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2002-05-08 01:35:51 +0000 |
commit | 848cfffbc5089b1711fe84eafa1c30ca6baf6d6f (patch) | |
tree | 71692d2a4a4dff145ad84912189a4227824176d1 /gdb/arm-tdep.c | |
parent | 2b8a5373e1ce837912558a50ed78b9bd3894a388 (diff) | |
download | gdb-848cfffbc5089b1711fe84eafa1c30ca6baf6d6f.zip gdb-848cfffbc5089b1711fe84eafa1c30ca6baf6d6f.tar.gz 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.c | 152 |
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. */ |