* arm-tdep.c (arm_skip_prologue): Handle generic dummy frames.
authorAndrew Cagney <cagney@redhat.com>
Wed, 8 May 2002 01:35:51 +0000 (01:35 +0000)
committerAndrew Cagney <cagney@redhat.com>
Wed, 8 May 2002 01:35:51 +0000 (01:35 +0000)
(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.

gdb/ChangeLog
gdb/arm-tdep.c

index 8bb4d0a..44440f7 100644 (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>
 
        * sh-tdep.c (sh_nofp_frame_init_saved_regs): Fix error in
index 2ea4d28..bc928e1 100644 (file)
@@ -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.  */