2002-05-03 Andrew Cagney * 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. Index: arm-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.57 diff -u -r1.57 arm-tdep.c --- arm-tdep.c 1 May 2002 00:57:51 -0000 1.57 +++ arm-tdep.c 4 May 2002 13:06:35 -0000 @@ -421,6 +421,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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_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 @@ 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,7 @@ tdep->lowest_pc = 0x20; tdep->jb_pc = -1; /* Longjump support not enabled by default. */ +#if 0 set_gdbarch_use_generic_dummy_frames (gdbarch, 0); /* Call dummy code. */ @@ -2912,6 +2935,27 @@ 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 +2975,11 @@ 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 0 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. */