This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] Use prologue-value.c for arm_analyze_prologue


This is a cleanup I've been meaning to do for a while.  It switches
the ARM prologue analyzer from an ad-hoc scanner to the mighty slick
prologue-value.[ch] infrastructure.  There are no functional changes,
but if someone wants to enhance the prologue analyzer later it should
be a bit simpler.  I also removed the no longer required distinction
between frame size and frame offset.

Tested on arm-none-eabi, with the dwarf2 unwinder disabled.  Checked in.

-- 
Daniel Jacobowitz
CodeSourcery

2007-10-10  Daniel Jacobowitz  <dan@codesourcery.com>

	* arm-tdep.c (struct arm_prologue_cache): Remove frameoffset.
	(thumb_analyze_prologue): Move pv_area_store_would_trash call
	out of loop.  Do not set cache->frameoffset.
	(arm_scan_prologue): Use prologue-value mechanism.  Do not set
	frameoffset.  Simplify framesize.
	(arm_make_prologue_cache, arm_normal_frame_base): Do not use
	frameoffset.
	* arm-tdep.h (enum gdb_regnum): Add ARM_IP_REGNUM.

Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.244
diff -u -p -r1.244 arm-tdep.c
--- arm-tdep.c	8 Oct 2007 12:49:03 -0000	1.244
+++ arm-tdep.c	10 Oct 2007 14:00:28 -0000
@@ -187,13 +187,11 @@ struct arm_prologue_cache
      to identify this frame.  */
   CORE_ADDR prev_sp;
 
-  /* The frame base for this frame is just prev_sp + frame offset -
-     frame size.  FRAMESIZE is the size of this stack frame, and
-     FRAMEOFFSET if the initial offset from the stack pointer (this
-     frame's stack pointer, not PREV_SP) to the frame base.  */
+  /* The frame base for this frame is just prev_sp - frame size.
+     FRAMESIZE is the distance from the frame pointer to the
+     initial stack pointer.  */
 
   int framesize;
-  int frameoffset;
 
   /* The register used to hold the frame pointer for this frame.  */
   int framereg;
@@ -292,7 +290,9 @@ thumb_analyze_prologue (struct gdbarch *
 	{
 	  int regno;
 	  int mask;
-	  int stop = 0;
+
+	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	    break;
 
 	  /* Bits 0-7 contain a mask for registers R0-R7.  Bit 8 says
 	     whether to save LR (R14).  */
@@ -302,19 +302,10 @@ thumb_analyze_prologue (struct gdbarch *
 	  for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
 	    if (mask & (1 << regno))
 	      {
-		if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
-		  {
-		    stop = 1;
-		    break;
-		  }
-
 		regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
 						       -4);
 		pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
 	      }
-
-	  if (stop)
-	    break;
 	}
       else if ((insn & 0xff00) == 0xb000)	/* add sp, #simm  OR  
 						   sub sp, #simm */
@@ -370,9 +361,6 @@ thumb_analyze_prologue (struct gdbarch *
       return start;
     }
 
-  /* frameoffset is unused for this unwinder.  */
-  cache->frameoffset = 0;
-
   if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
     {
       /* Frame pointer is fp.  Frame size is constant.  */
@@ -652,14 +640,17 @@ arm_scan_prologue (struct frame_info *ne
 		   struct arm_prologue_cache *cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  int regno, sp_offset, fp_offset, ip_offset;
+  int regno;
   CORE_ADDR prologue_start, prologue_end, current_pc;
   CORE_ADDR prev_pc = frame_pc_unwind (next_frame);
+  pv_t regs[ARM_FPS_REGNUM];
+  struct pv_area *stack;
+  struct cleanup *back_to;
+  CORE_ADDR offset;
 
   /* Assume there is no frame until proven otherwise.  */
   cache->framereg = ARM_SP_REGNUM;
   cache->framesize = 0;
-  cache->frameoffset = 0;
 
   /* Check for Thumb prologue.  */
   if (arm_pc_is_thumb (prev_pc))
@@ -754,7 +745,12 @@ arm_scan_prologue (struct frame_info *ne
      in which case it is often (but not always) replaced by
      "str lr, [sp, #-4]!".  - Michael Snyder, 2002-04-23]  */
 
-  sp_offset = fp_offset = ip_offset = 0;
+  for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
+    regs[regno] = pv_register (regno, 0);
+  stack = make_pv_area (ARM_SP_REGNUM);
+  back_to = make_cleanup_free_pv_area (stack);
+
+  regs[ARM_PC_REGNUM] = pv_unknown ();
 
   for (current_pc = prologue_start;
        current_pc < prologue_end;
@@ -764,7 +760,7 @@ arm_scan_prologue (struct frame_info *ne
 
       if (insn == 0xe1a0c00d)		/* mov ip, sp */
 	{
-	  ip_offset = 0;
+	  regs[ARM_IP_REGNUM] = regs[ARM_SP_REGNUM];
 	  continue;
 	}
       else if ((insn & 0xfffff000) == 0xe28dc000) /* add ip, sp #n */
@@ -772,7 +768,7 @@ arm_scan_prologue (struct frame_info *ne
 	  unsigned imm = insn & 0xff;                   /* immediate value */
 	  unsigned rot = (insn & 0xf00) >> 7;           /* rotate amount */
 	  imm = (imm >> rot) | (imm << (32 - rot));
-	  ip_offset = imm;
+	  regs[ARM_IP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], imm);
 	  continue;
 	}
       else if ((insn & 0xfffff000) == 0xe24dc000) /* sub ip, sp #n */
@@ -780,13 +776,15 @@ arm_scan_prologue (struct frame_info *ne
 	  unsigned imm = insn & 0xff;                   /* immediate value */
 	  unsigned rot = (insn & 0xf00) >> 7;           /* rotate amount */
 	  imm = (imm >> rot) | (imm << (32 - rot));
-	  ip_offset = -imm;
+	  regs[ARM_IP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
 	  continue;
 	}
       else if (insn == 0xe52de004)	/* str lr, [sp, #-4]! */
 	{
-	  sp_offset -= 4;
-	  cache->saved_regs[ARM_LR_REGNUM].addr = sp_offset;
+	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	    break;
+	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -4);
+	  pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[ARM_LR_REGNUM]);
 	  continue;
 	}
       else if ((insn & 0xffff0000) == 0xe92d0000)
@@ -796,12 +794,15 @@ arm_scan_prologue (struct frame_info *ne
 	{
 	  int mask = insn & 0xffff;
 
+	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	    break;
+
 	  /* Calculate offsets of saved registers.  */
 	  for (regno = ARM_PC_REGNUM; regno >= 0; regno--)
 	    if (mask & (1 << regno))
 	      {
-		sp_offset -= 4;
-		cache->saved_regs[regno].addr = sp_offset;
+		regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -4);
+		pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
 	      }
 	}
       else if ((insn & 0xffffc000) == 0xe54b0000 ||	/* strb rx,[r11,#-n] */
@@ -823,22 +824,24 @@ arm_scan_prologue (struct frame_info *ne
 	  unsigned imm = insn & 0xff;			/* immediate value */
 	  unsigned rot = (insn & 0xf00) >> 7;		/* rotate amount */
 	  imm = (imm >> rot) | (imm << (32 - rot));
-	  fp_offset = -imm + ip_offset;
-	  cache->framereg = ARM_FP_REGNUM;
+	  regs[ARM_FP_REGNUM] = pv_add_constant (regs[ARM_IP_REGNUM], -imm);
 	}
       else if ((insn & 0xfffff000) == 0xe24dd000)	/* sub sp, sp #n */
 	{
 	  unsigned imm = insn & 0xff;			/* immediate value */
 	  unsigned rot = (insn & 0xf00) >> 7;		/* rotate amount */
 	  imm = (imm >> rot) | (imm << (32 - rot));
-	  sp_offset -= imm;
+	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -imm);
 	}
       else if ((insn & 0xffff7fff) == 0xed6d0103	/* stfe f?, [sp, -#c]! */
 	       && gdbarch_tdep (gdbarch)->have_fpa_registers)
 	{
-	  sp_offset -= 12;
+	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	    break;
+
+	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
 	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
-	  cache->saved_regs[regno].addr = sp_offset;
+	  pv_area_store (stack, regs[ARM_SP_REGNUM], 12, regs[regno]);
 	}
       else if ((insn & 0xffbf0fff) == 0xec2d0200	/* sfmfd f0, 4, [sp!] */
 	       && gdbarch_tdep (gdbarch)->have_fpa_registers)
@@ -846,6 +849,9 @@ arm_scan_prologue (struct frame_info *ne
 	  int n_saved_fp_regs;
 	  unsigned int fp_start_reg, fp_bound_reg;
 
+	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	    break;
+
 	  if ((insn & 0x800) == 0x800)		/* N0 is set */
 	    {
 	      if ((insn & 0x40000) == 0x40000)	/* N1 is set */
@@ -865,8 +871,9 @@ arm_scan_prologue (struct frame_info *ne
 	  fp_bound_reg = fp_start_reg + n_saved_fp_regs;
 	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
 	    {
-	      sp_offset -= 12;
-	      cache->saved_regs[fp_start_reg++].addr = sp_offset;
+	      regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
+	      pv_area_store (stack, regs[ARM_SP_REGNUM], 12,
+			     regs[fp_start_reg++]);
 	    }
 	}
       else if ((insn & 0xf0000000) != 0xe0000000)
@@ -879,14 +886,32 @@ arm_scan_prologue (struct frame_info *ne
 	continue;
     }
 
-  /* The frame size is just the negative of the offset (from the
-     original SP) of the last thing thing we pushed on the stack. 
-     The frame offset is [new FP] - [new SP].  */
-  cache->framesize = -sp_offset;
-  if (cache->framereg == ARM_FP_REGNUM)
-    cache->frameoffset = fp_offset - sp_offset;
+  /* The frame size is just the distance from the frame register
+     to the original stack pointer.  */
+  if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
+    {
+      /* Frame pointer is fp.  */
+      cache->framereg = ARM_FP_REGNUM;
+      cache->framesize = -regs[ARM_FP_REGNUM].k;
+    }
+  else if (pv_is_register (regs[ARM_SP_REGNUM], ARM_SP_REGNUM))
+    {
+      /* Try the stack pointer... this is a bit desperate.  */
+      cache->framereg = ARM_SP_REGNUM;
+      cache->framesize = -regs[ARM_SP_REGNUM].k;
+    }
   else
-    cache->frameoffset = 0;
+    {
+      /* We're just out of luck.  We don't know where the frame is.  */
+      cache->framereg = -1;
+      cache->framesize = 0;
+    }
+
+  for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
+    if (pv_area_find_reg (stack, gdbarch, regno, &offset))
+      cache->saved_regs[regno].addr = offset;
+
+  do_cleanups (back_to);
 }
 
 static struct arm_prologue_cache *
@@ -905,7 +930,7 @@ arm_make_prologue_cache (struct frame_in
   if (unwound_fp == 0)
     return cache;
 
-  cache->prev_sp = unwound_fp + cache->framesize - cache->frameoffset;
+  cache->prev_sp = unwound_fp + cache->framesize;
 
   /* Calculate actual addresses of saved registers using offsets
      determined by arm_scan_prologue.  */
@@ -1057,7 +1082,7 @@ arm_normal_frame_base (struct frame_info
     *this_cache = arm_make_prologue_cache (next_frame);
   cache = *this_cache;
 
-  return cache->prev_sp + cache->frameoffset - cache->framesize;
+  return cache->prev_sp - cache->framesize;
 }
 
 struct frame_base arm_normal_base = {
Index: arm-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.h,v
retrieving revision 1.27
diff -u -p -r1.27 arm-tdep.h
--- arm-tdep.h	27 Sep 2007 18:48:33 -0000	1.27
+++ arm-tdep.h	10 Oct 2007 14:00:28 -0000
@@ -29,6 +29,7 @@ enum gdb_regnum {
   ARM_A1_REGNUM = 0,		/* first integer-like argument */
   ARM_A4_REGNUM = 3,		/* last integer-like argument */
   ARM_AP_REGNUM = 11,
+  ARM_IP_REGNUM = 12,
   ARM_SP_REGNUM = 13,		/* Contains address of top of stack */
   ARM_LR_REGNUM = 14,		/* address to return to from a function call */
   ARM_PC_REGNUM = 15,		/* Contains program counter */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]