[RFA] Repost ARM frame patches

Daniel Jacobowitz drow@mvista.com
Fri Aug 29 01:50:00 GMT 2003


Updated to current HEAD.  The only changes needed were frame_unwind_p
-> frame_unwind_sniffer.  They still work :)  Also attached is the
fourth patch in the series, which enables the dwarf2 unwinder.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer
-------------- next part --------------
This patch is mostly cosmetic.  It creates an "unwind cache", and uses
it to control the interface to thumb_scan_prologue and arm_scan_prologue.
Those functions work from an unwound PC and SP only (although the use of the
unwound SP is a little odd...) and produce the saved_regs and extra_info
data.  For now, I stash the cache in frame_extra_info.  Don't worry, not for
long :)

This patch causes a memory increase per frame, in that the saved_regs array
is now duplicated.  The third patch will remove the other copy.

2003-08-28  Daniel Jacobowitz  <drow@mvista.com>

	* arm-tdep.c (arm_get_cache): Define.
	(struct arm_prologue_cache): Renamed from frame_extra_info.  Add
	unwound_sp, unwound_pc, and saved_regs.
	(thumb_scan_prologue): Take a cache instead of the frame.
	(arm_scan_prologue): Likewise.
	(arm_frame_chain): Create a temporary cache for arm_scan_prologue
	instead of a temporary frame.
	(arm_init_extra_frame_info): Allocate and use a cache.
	(arm_frame_saved_pc, arm_pop_frame): Use the cache.

Index: gdb/arm-tdep.c
===================================================================
--- gdb.orig/arm-tdep.c	2003-08-28 21:13:42.000000000 -0400
+++ gdb/arm-tdep.c	2003-08-28 21:13:45.000000000 -0400
@@ -161,11 +161,15 @@ static void convert_to_extended (const s
    pointer from the stack pointer (for frameless functions, and when
    we're still in the prologue of a function with a frame).  */
 
-struct frame_extra_info
+#define arm_get_cache(fi) ((struct arm_prologue_cache *) get_frame_extra_info (fi))
+
+struct arm_prologue_cache
 {
+  CORE_ADDR unwound_sp, unwound_pc;
   int framesize;
   int frameoffset;
   int framereg;
+  CORE_ADDR saved_regs[1];
 };
 
 /* Addresses for calling Thumb functions have the bit 0 set.
@@ -519,7 +523,7 @@ arm_skip_prologue (CORE_ADDR pc)
 /* *INDENT-ON* */
 
 static void
-thumb_scan_prologue (struct frame_info *fi)
+thumb_scan_prologue (struct arm_prologue_cache *cache)
 {
   CORE_ADDR prologue_start;
   CORE_ADDR prologue_end;
@@ -535,16 +539,15 @@ thumb_scan_prologue (struct frame_info *
   int i;
 
   /* Don't try to scan dummy frames.  */
-  if (fi != NULL
-      && DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
+  if (DEPRECATED_PC_IN_CALL_DUMMY (cache->unwound_pc, 0, 0))
     return;
 
-  if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
+  if (find_pc_partial_function (cache->unwound_pc, NULL, &prologue_start, &prologue_end))
     {
       struct symtab_and_line sal = find_pc_line (prologue_start, 0);
 
       if (sal.line == 0)		/* no line info, use current PC  */
-	prologue_end = get_frame_pc (fi);
+	prologue_end = cache->unwound_pc;
       else if (sal.end < prologue_end)	/* next line begins after fn end */
 	prologue_end = sal.end;		/* (probably means no prologue)  */
     }
@@ -553,7 +556,7 @@ thumb_scan_prologue (struct frame_info *
        16 pushes, an add, and "mv fp,sp".  */
     prologue_end = prologue_start + 40;
 
-  prologue_end = min (prologue_end, get_frame_pc (fi));
+  prologue_end = min (prologue_end, cache->unwound_pc);
 
   /* Initialize the saved register map.  When register H is copied to
      register L, we will put H in saved_reg[L].  */
@@ -564,7 +567,7 @@ thumb_scan_prologue (struct frame_info *
      frame pointer, adjust the stack pointer, and save registers.
      Do this until all basic prolog instructions are found.  */
 
-  get_frame_extra_info (fi)->framesize = 0;
+  cache->framesize = 0;
   for (current_pc = prologue_start;
        (current_pc < prologue_end) && ((findmask & 7) != 7);
        current_pc += 2)
@@ -587,9 +590,8 @@ thumb_scan_prologue (struct frame_info *
 	  for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
 	    if (mask & (1 << regno))
 	      {
-		get_frame_extra_info (fi)->framesize += 4;
-		get_frame_saved_regs (fi)[saved_reg[regno]] =
-		  -(get_frame_extra_info (fi)->framesize);
+		cache->framesize += 4;
+		cache->saved_regs[saved_reg[regno]] = -cache->framesize;
 		/* Reset saved register map.  */
 		saved_reg[regno] = regno;
 	      }
@@ -605,23 +607,23 @@ thumb_scan_prologue (struct frame_info *
 	  offset = (insn & 0x7f) << 2;		/* get scaled offset */
 	  if (insn & 0x80)		/* is it signed? (==subtracting) */
 	    {
-	      get_frame_extra_info (fi)->frameoffset += offset;
+	      cache->frameoffset += offset;
 	      offset = -offset;
 	    }
-	  get_frame_extra_info (fi)->framesize -= offset;
+	  cache->framesize -= offset;
 	}
       else if ((insn & 0xff00) == 0xaf00)	/* add r7, sp, #imm */
 	{
 	  findmask |= 2;			/* setting of r7 found */
-	  get_frame_extra_info (fi)->framereg = THUMB_FP_REGNUM;
+	  cache->framereg = THUMB_FP_REGNUM;
 	  /* get scaled offset */
-	  get_frame_extra_info (fi)->frameoffset = (insn & 0xff) << 2;
+	  cache->frameoffset = (insn & 0xff) << 2;
 	}
       else if (insn == 0x466f)			/* mov r7, sp */
 	{
 	  findmask |= 2;			/* setting of r7 found */
-	  get_frame_extra_info (fi)->framereg = THUMB_FP_REGNUM;
-	  get_frame_extra_info (fi)->frameoffset = 0;
+	  cache->framereg = THUMB_FP_REGNUM;
+	  cache->frameoffset = 0;
 	  saved_reg[THUMB_FP_REGNUM] = ARM_SP_REGNUM;
 	}
       else if ((insn & 0xffc0) == 0x4640)	/* mov r0-r7, r8-r15 */
@@ -706,27 +708,27 @@ thumb_scan_prologue (struct frame_info *
  */
 
 static void
-arm_scan_prologue (struct frame_info *fi)
+arm_scan_prologue (struct arm_prologue_cache *cache)
 {
   int regno, sp_offset, fp_offset;
   LONGEST return_value;
   CORE_ADDR prologue_start, prologue_end, current_pc;
 
   /* Assume there is no frame until proven otherwise.  */
-  get_frame_extra_info (fi)->framereg = ARM_SP_REGNUM;
-  get_frame_extra_info (fi)->framesize = 0;
-  get_frame_extra_info (fi)->frameoffset = 0;
+  cache->framereg = ARM_SP_REGNUM;
+  cache->framesize = 0;
+  cache->frameoffset = 0;
 
   /* Check for Thumb prologue.  */
-  if (arm_pc_is_thumb (get_frame_pc (fi)))
+  if (arm_pc_is_thumb (cache->unwound_pc))
     {
-      thumb_scan_prologue (fi);
+      thumb_scan_prologue (cache);
       return;
     }
 
   /* Find the function prologue.  If we can't find the function in
      the symbol table, peek in the stack frame to find the PC.  */
-  if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
+  if (find_pc_partial_function (cache->unwound_pc, NULL, &prologue_start, &prologue_end))
     {
       /* One way to find the end of the prologue (which works well
          for unoptimized code) is to do the following:
@@ -734,7 +736,7 @@ arm_scan_prologue (struct frame_info *fi
 	    struct symtab_and_line sal = find_pc_line (prologue_start, 0);
 
 	    if (sal.line == 0)
-	      prologue_end = get_frame_pc (fi);
+	      prologue_end = cache->unwound_pc;
 	    else if (sal.end < prologue_end)
 	      prologue_end = sal.end;
 
@@ -769,7 +771,7 @@ arm_scan_prologue (struct frame_info *fi
     {
       /* Get address of the stmfd in the prologue of the callee; 
          the saved PC is the address of the stmfd + 8.  */
-      if (!safe_read_memory_integer (get_frame_base (fi), 4,  &return_value))
+      if (!safe_read_memory_integer (cache->unwound_sp, 4,  &return_value))
         return;
       else
         {
@@ -828,7 +830,7 @@ arm_scan_prologue (struct frame_info *fi
 	    if (mask & (1 << regno))
 	      {
 		sp_offset -= 4;
-		get_frame_saved_regs (fi)[regno] = sp_offset;
+		cache->saved_regs[regno] = sp_offset;
 	      }
 	}
       else if ((insn & 0xffffc000) == 0xe54b0000 ||	/* strb rx,[r11,#-n] */
@@ -851,7 +853,7 @@ arm_scan_prologue (struct frame_info *fi
 	  unsigned rot = (insn & 0xf00) >> 7;		/* rotate amount */
 	  imm = (imm >> rot) | (imm << (32 - rot));
 	  fp_offset = -imm;
-	  get_frame_extra_info (fi)->framereg = ARM_FP_REGNUM;
+	  cache->framereg = ARM_FP_REGNUM;
 	}
       else if ((insn & 0xfffff000) == 0xe24dd000)	/* sub sp, sp #n */
 	{
@@ -864,7 +866,7 @@ arm_scan_prologue (struct frame_info *fi
 	{
 	  sp_offset -= 12;
 	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
-	  get_frame_saved_regs (fi)[regno] = sp_offset;
+	  cache->saved_regs[regno] = sp_offset;
 	}
       else if ((insn & 0xffbf0fff) == 0xec2d0200)	/* sfmfd f0, 4, [sp!] */
 	{
@@ -891,7 +893,7 @@ arm_scan_prologue (struct frame_info *fi
 	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
 	    {
 	      sp_offset -= 12;
-	      get_frame_saved_regs (fi)[fp_start_reg++] = sp_offset;
+	      cache->saved_regs[fp_start_reg++] = sp_offset;
 	    }
 	}
       else if ((insn & 0xf0000000) != 0xe0000000)
@@ -907,11 +909,11 @@ arm_scan_prologue (struct frame_info *fi
   /* 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].  */
-  get_frame_extra_info (fi)->framesize = -sp_offset;
-  if (get_frame_extra_info (fi)->framereg == ARM_FP_REGNUM)
-    get_frame_extra_info (fi)->frameoffset = fp_offset - sp_offset;
+  cache->framesize = -sp_offset;
+  if (cache->framereg == ARM_FP_REGNUM)
+    cache->frameoffset = fp_offset - sp_offset;
   else
-    get_frame_extra_info (fi)->frameoffset = 0;
+    cache->frameoffset = 0;
 }
 
 /* Find REGNUM on the stack.  Otherwise, it's in an active register.
@@ -957,7 +959,7 @@ static CORE_ADDR
 arm_frame_chain (struct frame_info *fi)
 {
   CORE_ADDR caller_pc;
-  int framereg = get_frame_extra_info (fi)->framereg;
+  int framereg = arm_get_cache (fi)->framereg;
 
   if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
     /* A generic call dummy's frame is the same as caller's.  */
@@ -974,18 +976,18 @@ arm_frame_chain (struct frame_info *fi)
      So we must scan the prologue of the caller to determine its
      frame register number.  */
   /* XXX Fixme, we should try to do this without creating a temporary
-     caller_fi.  */
+     cache!  */
   if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (get_frame_pc (fi)))
     {
-      struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-      struct frame_info *caller_fi =
-	deprecated_frame_xmalloc_with_cleanup (SIZEOF_FRAME_SAVED_REGS,
-					       sizeof (struct frame_extra_info));
+      struct arm_prologue_cache *cache
+	= xcalloc (1, sizeof (struct arm_prologue_cache)
+		   + (NUM_REGS + NUM_PSEUDO_REGS - 1) * sizeof (CORE_ADDR));
+      struct cleanup *old_chain = make_cleanup (xfree, cache);
 
       /* Now, scan the prologue and obtain the frame register.  */
-      deprecated_update_frame_pc_hack (caller_fi, caller_pc);
-      arm_scan_prologue (caller_fi);
-      framereg = get_frame_extra_info (caller_fi)->framereg;
+      cache->unwound_pc = caller_pc;
+      arm_scan_prologue (cache);
+      framereg = cache->framereg;
 
       /* Deallocate the storage associated with the temporary frame
 	 created above.  */
@@ -997,7 +999,7 @@ arm_frame_chain (struct frame_info *fi)
   if (framereg == ARM_FP_REGNUM || framereg == THUMB_FP_REGNUM)
     return arm_find_callers_reg (fi, framereg);
   else
-    return get_frame_base (fi) + get_frame_extra_info (fi)->framesize;
+    return get_frame_base (fi) + arm_get_cache (fi)->framesize;
 }
 
 /* This function actually figures out the frame address for a given pc
@@ -1018,11 +1020,9 @@ arm_init_extra_frame_info (int fromleaf,
   if (get_frame_saved_regs (fi) == NULL)
     frame_saved_regs_zalloc (fi);
 
-  frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
-
-  get_frame_extra_info (fi)->framesize = 0;
-  get_frame_extra_info (fi)->frameoffset = 0;
-  get_frame_extra_info (fi)->framereg = 0;
+  frame_extra_info_zalloc (fi, (sizeof (struct arm_prologue_cache)
+				+ ((NUM_REGS + NUM_PSEUDO_REGS - 1)
+				   * sizeof (CORE_ADDR))));
 
   if (get_next_frame (fi))
     deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
@@ -1041,8 +1041,8 @@ arm_init_extra_frame_info (int fromleaf,
 					 ARM_SP_REGNUM);
   else
     sp = (get_frame_base (get_next_frame (fi))
-	  - get_frame_extra_info (get_next_frame (fi))->frameoffset
-	  + get_frame_extra_info (get_next_frame (fi))->framesize);
+	  - arm_get_cache (get_next_frame (fi))->frameoffset
+	  + arm_get_cache (get_next_frame (fi))->framesize);
 
   /* Determine whether or not we're in a sigtramp frame.
      Unfortunately, it isn't sufficient to test (get_frame_type (fi)
@@ -1068,30 +1068,33 @@ arm_init_extra_frame_info (int fromleaf,
 	get_frame_saved_regs (fi)[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, get_frame_pc (fi), reg);
 
       /* FIXME: What about thumb mode?  */
-      get_frame_extra_info (fi)->framereg = ARM_SP_REGNUM;
-      deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (fi)[get_frame_extra_info (fi)->framereg], REGISTER_RAW_SIZE (get_frame_extra_info (fi)->framereg)));
-      get_frame_extra_info (fi)->framesize = 0;
-      get_frame_extra_info (fi)->frameoffset = 0;
+      arm_get_cache (fi)->framereg = ARM_SP_REGNUM;
+      deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (fi)[arm_get_cache (fi)->framereg], REGISTER_RAW_SIZE (arm_get_cache (fi)->framereg)));
+      arm_get_cache (fi)->framesize = 0;
+      arm_get_cache (fi)->frameoffset = 0;
 
     }
   else
     {
-      arm_scan_prologue (fi);
+      arm_get_cache (fi)->unwound_pc = get_frame_pc (fi);
+      arm_get_cache (fi)->unwound_sp = get_frame_base (fi);
+
+      arm_scan_prologue (arm_get_cache (fi));
 
       if (!get_next_frame (fi))
 	/* This is the innermost frame?  */
-	deprecated_update_frame_base_hack (fi, read_register (get_frame_extra_info (fi)->framereg));
+	deprecated_update_frame_base_hack (fi, read_register (arm_get_cache (fi)->framereg));
       else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (get_next_frame (fi)), 0, 0))
 	/* Next inner most frame is a dummy, just grab its frame.
            Dummy frames always have the same FP as their caller.  */
 	deprecated_update_frame_base_hack (fi, get_frame_base (get_next_frame (fi)));
-      else if (get_frame_extra_info (fi)->framereg == ARM_FP_REGNUM
-	       || get_frame_extra_info (fi)->framereg == THUMB_FP_REGNUM)
+      else if (arm_get_cache (fi)->framereg == ARM_FP_REGNUM
+	       || arm_get_cache (fi)->framereg == THUMB_FP_REGNUM)
 	{
 	  /* not the innermost frame */
 	  /* If we have an FP, the callee saved it.  */
-	  if (get_frame_saved_regs (get_next_frame (fi))[get_frame_extra_info (fi)->framereg] != 0)
-	    deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (get_next_frame (fi))[get_frame_extra_info (fi)->framereg], 4));
+	  if (get_frame_saved_regs (get_next_frame (fi))[arm_get_cache (fi)->framereg] != 0)
+	    deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (get_next_frame (fi))[arm_get_cache (fi)->framereg], 4));
 	  else if (fromleaf)
 	    /* If we were called by a frameless fn.  then our frame is
 	       still in the frame pointer register on the board...  */
@@ -1101,11 +1104,11 @@ arm_init_extra_frame_info (int fromleaf,
       /* Calculate actual addresses of saved registers using offsets
          determined by arm_scan_prologue.  */
       for (reg = 0; reg < NUM_REGS; reg++)
-	if (get_frame_saved_regs (fi)[reg] != 0)
-	  get_frame_saved_regs (fi)[reg]
-	    += (get_frame_base (fi)
-		+ get_frame_extra_info (fi)->framesize
-		- get_frame_extra_info (fi)->frameoffset);
+	if (arm_get_cache (fi)->saved_regs[reg] != 0)
+	  get_frame_saved_regs (fi)[reg] = (arm_get_cache (fi)->saved_regs[reg]
+					    + get_frame_base (fi)
+					    + arm_get_cache (fi)->framesize
+					    - arm_get_cache (fi)->frameoffset);
     }
 }
 
@@ -1128,7 +1131,7 @@ arm_frame_saved_pc (struct frame_info *f
 
   if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi),
 				   (get_frame_base (fi)
-				    - get_frame_extra_info (fi)->frameoffset),
+				    - arm_get_cache (fi)->frameoffset),
 				   get_frame_base (fi)))
     {
       return read_memory_integer (get_frame_saved_regs (fi)[ARM_PC_REGNUM],
@@ -1321,8 +1324,8 @@ arm_pop_frame (void)
   int regnum;
   struct frame_info *frame = get_current_frame ();
   CORE_ADDR old_SP = (get_frame_base (frame)
-		      - get_frame_extra_info (frame)->frameoffset
-		      + get_frame_extra_info (frame)->framesize);
+		      - arm_get_cache (frame)->frameoffset
+		      + arm_get_cache (frame)->framesize);
 
   if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
 				   get_frame_base (frame),
-------------- next part --------------
This patch changes ARM to build an entire cache before setting any
information in the frame.  It includes some nasty hacks (for instance,
at one point it calls deprecated_get_next_frame_hack to get the sentinel
frame); don't worry, I swear they'll all go away in patch #3.  It adds one
FIXME, which also goes away in patch #3.

The basic point of this patch is to remove all uses of
deprecated_update_frame_base_hack.  It also eliminates the need for the
"fromleaf" argument to arm_init_extra_frame_info by checking for a frameless
function in the right place.  There are no functional changes.

2003-08-28  Daniel Jacobowitz  <drow@mvista.com>

	* arm-tdep.c (arm_minimal_frame_chain): Renamed from
	arm_frame_chain.  Take NEXT_FRAME and CACHE arguments.
	Use the cache instead of DEPRECATED_FRAME_SAVED_PC.
	(arm_minimal_frame_info): Renamed from arm_init_extra_frame_info.
	Take NEXT_FRAME and CACHE arguments.  Call
	FRAMELESS_FUNCTION_INVOCATION instead of checking FROMLEAF argument.
	Set unwound_pc in CACHE instead of modifying the frame argument.
	Don't bother checking the frame type when looking for sigtramp
	frames.
	(arm_make_prologue_cache, arm_frame_chain)
	(arm_init_extra_frame_info): New functions.

Index: gdb/arm-tdep.c
===================================================================
--- gdb.orig/arm-tdep.c	2003-08-28 21:13:45.000000000 -0400
+++ gdb/arm-tdep.c	2003-08-28 21:13:45.000000000 -0400
@@ -955,21 +955,19 @@ arm_find_callers_reg (struct frame_info 
    DEPRECATED_INIT_FRAME_PC will be called for the new frame.  For
    ARM, we save the frame size when we initialize the frame_info.  */
 
-static CORE_ADDR
-arm_frame_chain (struct frame_info *fi)
+CORE_ADDR
+arm_minimal_frame_chain (struct frame_info *next_frame, struct arm_prologue_cache *cache)
 {
   CORE_ADDR caller_pc;
-  int framereg = arm_get_cache (fi)->framereg;
+  int framereg = arm_get_cache (next_frame)->framereg;
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
-    /* A generic call dummy's frame is the same as caller's.  */
-    return get_frame_base (fi);
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (next_frame), 0, 0))
+    return get_frame_base (next_frame);
 
-  if (get_frame_pc (fi) < LOWEST_PC)
+  if (get_frame_pc (next_frame) < LOWEST_PC)
     return 0;
 
-  /* If the caller is the startup code, we're at the end of the chain.  */
-  caller_pc = DEPRECATED_FRAME_SAVED_PC (fi);
+  caller_pc = cache->unwound_pc;
 
   /* If the caller is Thumb and the caller is ARM, or vice versa,
      the frame register of the caller is different from ours.
@@ -977,7 +975,12 @@ arm_frame_chain (struct frame_info *fi)
      frame register number.  */
   /* XXX Fixme, we should try to do this without creating a temporary
      cache!  */
-  if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (get_frame_pc (fi)))
+  /* NOTE drow/2003-06-26: I'm quite suspicious of this code... what is it
+     really doing?  I have the feeling that it's trying to handle the case
+     where my framereg is ARM_FP_REGNUM, and my (Thumb) caller's framereg is
+     THUMB_FP_REGNUM, and switching between the two.  But the unwinder should
+     be taking care of that.  */
+  if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (get_frame_pc (next_frame)))
     {
       struct arm_prologue_cache *cache
 	= xcalloc (1, sizeof (struct arm_prologue_cache)
@@ -997,52 +1000,45 @@ arm_frame_chain (struct frame_info *fi)
   /* If the caller used a frame register, return its value.
      Otherwise, return the caller's stack pointer.  */
   if (framereg == ARM_FP_REGNUM || framereg == THUMB_FP_REGNUM)
-    return arm_find_callers_reg (fi, framereg);
+    return arm_find_callers_reg (next_frame, framereg);
   else
-    return get_frame_base (fi) + arm_get_cache (fi)->framesize;
+    /* FIXME drow/2003-06-26: The next frame is an opaque thing at this point,
+       we should only be using frame methods on it.  What if it's a dummy
+       frame, calling a frameless function (framereg == ARM_SP_REGNUM)?  Test
+       it.  */
+    return get_frame_base (next_frame) + arm_get_cache (next_frame)->framesize;
 }
 
 /* This function actually figures out the frame address for a given pc
    and sp.  This is tricky because we sometimes don't use an explicit
    frame pointer, and the previous stack pointer isn't necessarily
    recorded on the stack.  The only reliable way to get this info is
-   to examine the prologue.  FROMLEAF is a little confusing, it means
-   this is the next frame up the chain AFTER a frameless function.  If
-   this is true, then the frame value for this frame is still in the
-   fp register.  */
+   to examine the prologue.  */
 
 static void
-arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+arm_minimal_frame_info (struct frame_info *next_frame,
+			struct arm_prologue_cache *cache)
 {
   int reg;
   CORE_ADDR sp;
 
-  if (get_frame_saved_regs (fi) == NULL)
-    frame_saved_regs_zalloc (fi);
-
-  frame_extra_info_zalloc (fi, (sizeof (struct arm_prologue_cache)
-				+ ((NUM_REGS + NUM_PSEUDO_REGS - 1)
-				   * sizeof (CORE_ADDR))));
-
-  if (get_next_frame (fi))
-    deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
-
-  memset (get_frame_saved_regs (fi), '\000', sizeof get_frame_saved_regs (fi));
+  memset (cache->saved_regs, '\000', sizeof (CORE_ADDR) * (NUM_REGS + NUM_PSEUDO_REGS));
 
   /* Compute stack pointer for this frame.  We use this value for both
      the sigtramp and call dummy cases.  */
-  if (!get_next_frame (fi))
-    sp = read_sp();
-  else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (get_next_frame (fi)), 0, 0))
+
+  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (next_frame), 0, 0))
     /* For generic dummy frames, pull the value direct from the frame.
        Having an unwind function to do this would be nice.  */
-    sp = deprecated_read_register_dummy (get_frame_pc (get_next_frame (fi)),
-					 get_frame_base (get_next_frame (fi)),
+    sp = deprecated_read_register_dummy (get_frame_pc (next_frame),
+					 get_frame_base (next_frame),
 					 ARM_SP_REGNUM);
+  else if (arm_get_cache (next_frame))
+    sp = (get_frame_base (next_frame)
+	  - arm_get_cache (next_frame)->frameoffset
+	  + arm_get_cache (next_frame)->framesize);
   else
-    sp = (get_frame_base (get_next_frame (fi))
-	  - arm_get_cache (get_next_frame (fi))->frameoffset
-	  + arm_get_cache (get_next_frame (fi))->framesize);
+    sp = read_sp ();  /* FIXME remove case */
 
   /* Determine whether or not we're in a sigtramp frame.
      Unfortunately, it isn't sufficient to test (get_frame_type (fi)
@@ -1061,57 +1057,106 @@ arm_init_extra_frame_info (int fromleaf,
      frame.c:get_prev_frame() is modified to set the frame's type
      before calling functions like this.  */
 
+  /* NOTE drow/2003-06-26: This will move to a predicate for a different unwinder shortly.  */
+
   if (SIGCONTEXT_REGISTER_ADDRESS_P () 
-      && ((get_frame_type (fi) == SIGTRAMP_FRAME) || PC_IN_SIGTRAMP (get_frame_pc (fi), (char *)0)))
+      && PC_IN_SIGTRAMP (cache->unwound_pc, (char *)0))
     {
       for (reg = 0; reg < NUM_REGS; reg++)
-	get_frame_saved_regs (fi)[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, get_frame_pc (fi), reg);
+	cache->saved_regs[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, cache->unwound_pc, reg);
 
       /* FIXME: What about thumb mode?  */
-      arm_get_cache (fi)->framereg = ARM_SP_REGNUM;
-      deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (fi)[arm_get_cache (fi)->framereg], REGISTER_RAW_SIZE (arm_get_cache (fi)->framereg)));
-      arm_get_cache (fi)->framesize = 0;
-      arm_get_cache (fi)->frameoffset = 0;
-
+      cache->framereg = ARM_SP_REGNUM;
+      cache->unwound_sp = read_memory_integer (cache->saved_regs[cache->framereg], REGISTER_RAW_SIZE (cache->framereg));
+      cache->framesize = 0;
+      cache->frameoffset = 0;
     }
   else
     {
-      arm_get_cache (fi)->unwound_pc = get_frame_pc (fi);
-      arm_get_cache (fi)->unwound_sp = get_frame_base (fi);
+      /* At this point, the unwound sp is just the result of frame_chain.
+	 Then it gets changed below.  */
 
-      arm_scan_prologue (arm_get_cache (fi));
+      arm_scan_prologue (cache);
 
-      if (!get_next_frame (fi))
+      if (!next_frame)
 	/* This is the innermost frame?  */
-	deprecated_update_frame_base_hack (fi, read_register (arm_get_cache (fi)->framereg));
-      else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (get_next_frame (fi)), 0, 0))
+	cache->unwound_sp = read_register (cache->framereg);
+      else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (next_frame), 0, 0))
 	/* Next inner most frame is a dummy, just grab its frame.
            Dummy frames always have the same FP as their caller.  */
-	deprecated_update_frame_base_hack (fi, get_frame_base (get_next_frame (fi)));
-      else if (arm_get_cache (fi)->framereg == ARM_FP_REGNUM
-	       || arm_get_cache (fi)->framereg == THUMB_FP_REGNUM)
+	cache->unwound_sp = get_frame_base (next_frame);
+      else if (cache->framereg == ARM_FP_REGNUM
+	       || cache->framereg == THUMB_FP_REGNUM)
 	{
 	  /* not the innermost frame */
 	  /* If we have an FP, the callee saved it.  */
-	  if (get_frame_saved_regs (get_next_frame (fi))[arm_get_cache (fi)->framereg] != 0)
-	    deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (get_next_frame (fi))[arm_get_cache (fi)->framereg], 4));
-	  else if (fromleaf)
+	  if (get_frame_saved_regs (next_frame) /**/ && get_frame_saved_regs (next_frame)[cache->framereg] != 0)
+	    cache->unwound_sp = read_memory_integer (get_frame_saved_regs (next_frame)[cache->framereg], 4);
+	  else if (frame_relative_level (next_frame) == 0
+		   && FRAMELESS_FUNCTION_INVOCATION (next_frame))
 	    /* If we were called by a frameless fn.  then our frame is
 	       still in the frame pointer register on the board...  */
-	    deprecated_update_frame_base_hack (fi, deprecated_read_fp ());
+	    cache->unwound_sp = deprecated_read_fp ();
 	}
 
       /* Calculate actual addresses of saved registers using offsets
          determined by arm_scan_prologue.  */
       for (reg = 0; reg < NUM_REGS; reg++)
-	if (arm_get_cache (fi)->saved_regs[reg] != 0)
-	  get_frame_saved_regs (fi)[reg] = (arm_get_cache (fi)->saved_regs[reg]
-					    + get_frame_base (fi)
-					    + arm_get_cache (fi)->framesize
-					    - arm_get_cache (fi)->frameoffset);
+	if (cache->saved_regs[reg] != 0)
+	  cache->saved_regs[reg] = (cache->saved_regs[reg]
+				    + cache->unwound_sp
+				    + cache->framesize
+				    - cache->frameoffset);
     }
 }
 
+static struct arm_prologue_cache *
+arm_make_prologue_cache (struct frame_info *next_frame)
+{
+  struct arm_prologue_cache *cache;
+
+  cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache)
+				+ sizeof (CORE_ADDR) * (NUM_REGS + NUM_PSEUDO_REGS - 1));
+
+  cache->unwound_pc = frame_pc_unwind (next_frame);
+  if (frame_relative_level (next_frame) < 0)
+    cache->unwound_sp = deprecated_read_fp ();
+  else
+    cache->unwound_sp = arm_minimal_frame_chain (next_frame, cache);
+  arm_minimal_frame_info (next_frame, cache);
+
+  return cache;
+}
+
+static CORE_ADDR
+arm_frame_chain (struct frame_info *next_frame)
+{
+  struct arm_prologue_cache *cache;
+
+  cache = arm_make_prologue_cache (next_frame);
+  return cache->unwound_sp;
+}
+
+static void
+arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+{
+  struct arm_prologue_cache *cache;
+
+  cache = arm_make_prologue_cache (deprecated_get_next_frame_hack (fi));
+
+  if (get_frame_saved_regs (fi) == NULL)
+    frame_saved_regs_zalloc (fi);
+
+  frame_extra_info_zalloc (fi, (sizeof (struct arm_prologue_cache)
+				+ ((NUM_REGS + NUM_PSEUDO_REGS - 1)
+				   * sizeof (CORE_ADDR))));
+
+  memcpy (get_frame_extra_info (fi), cache,  (sizeof (struct arm_prologue_cache)
+					      + ((NUM_REGS + NUM_PSEUDO_REGS - 1)
+						 * sizeof (CORE_ADDR))));
+  memcpy (get_frame_saved_regs (fi), cache->saved_regs,
+	  (NUM_REGS + NUM_PSEUDO_REGS - 1) * sizeof (CORE_ADDR));
+}
 
 /* Find the caller of this frame.  We do this by seeing if ARM_LR_REGNUM
    is saved in the stack anywhere, otherwise we get it from the
-------------- next part --------------
Here we are.  This patch converts the ARM from a legacy frame target to a
modern frame target.  Unlike my previous patches, it does include functional
changes - quite a few of them.  I believe they are all improvements.  For
instance, previously, backtracing from a Thumb function, to an ARM caller,
to that function's caller, did not work - GDB would stop at the first ARM
function.  I've verified that we now get a correct backtrace with these
changes.

Another change of note is in arm_scan_prologue, in the case where
find_pc_partial_function fails (no symbols).  We used to go through some
extreme contortions in order to find a stack pointer value, which we
expected to have the saved PC from this function's prologue stored in it. 
With proper unwinding, all we need to do is ask the previous function for
our frame pointer.  This requires making the assumption (since we haven't
found, let alone analyzed, our prologue yet) that we have the normal frame
pointer - a better assumption than that we have the same frame pointer as
our caller, which is obviously wrong sometimes.  I've verified that this
works for normal code.

The trickery in arm_init_extra_frame_info where we scanned the caller's
prologue (according to the comments; but it was actually the callee)
to find its frame register.  It became unnecessary, and I'm pretty sure it
was wrong to begin with - the same off-by-one-frame headache I've been
fighting all week is creeping up behind my eyeballs again.

This includes the small varobj change I mentioned earlier today on gdb@:
call get_frame_base_address instead of get_frame_base.  It's a monotonic
improvement, but leaving it out should hurt nothing but the MI testsuite for
finding variables in different frames.

This patch was tested only for xscale-elf, on the simulator.  I'm going to
be pulling out an arm-linux target to test it on tomorrow, and will report
results.  No new regressions, no fixed regressions.  I get 49 failures, from
fileio.exp, huge.exp, store.exp, mi-var-display.exp/mi1-var-display.exp (the
compiler bug relating to "weird"), args.exp, bang.exp, and templates.exp. 
And some compile errors from shreloc.exp.

2003-08-28  Daniel Jacobowitz  <drow@mvista.com>

	* arm-tdep.c: Include frame-unwind.h, frame-base.h, and
	trad-frame.h.
	(arm_get_cache): Delete macro.
	(struct arm_prologue_cache): Update comments.  Make saved_regs into
	a trad_frame_saved_reg pointer.  Remove unwound_pc; rename unwound_sp
	to prev_sp.
	(thumb_scan_prologue): Update for cache changes.  Don't call
	DEPRECATED_PC_IN_CALL_DUMMY.
	(arm_scan_prologue): Update for cache changes.  Take NEXT_FRAME
	argument and use it in desperation search for our prologue.  Do not
	search past the specified PC.
	(arm_make_prologue_cache): Simplify.

	(arm_prologue_this_id, arm_prologue_prev_register)
	(arm_prologue_unwind, arm_prologue_unwind_sniffer)
	(arm_normal_frame_base, arm_normal_base, arm_make_sigtramp_cache)
	(arm_sigtramp_this_id, arm_sigtramp_prev_register)
	(arm_sigtramp_unwind, arm_sigtramp_unwind_sniffer)
	(arm_unwind_dummy_id, arm_unwind_pc, arm_unwind_sp): New.

	(arm_frame_chain_valid, arm_find_callers_reg)
	(arm_frame_saved_pc, arm_read_fp, arm_frame_init_saved_regs)
	(arm_pop_frame): Delete obsolete methods.
	(arm_minimal_frame_chain, arm_minimal_frame_info): Delete.

	(arm_gdbarch_init): Update for new frame methods.  Register prologue
	and sigtramp unwinders.  Set the default frame base method.

	* Makefile.in (arm-tdep.o): Update dependencies.
	* varobj.c (find_frame_addr_in_frame_chain): Call
	get_frame_base_address.
	* std-regs.c (value_of_builtin_frame_fp_reg): Likewise.

Index: gdb/arm-tdep.c
===================================================================
--- gdb.orig/arm-tdep.c	2003-08-28 21:13:45.000000000 -0400
+++ gdb/arm-tdep.c	2003-08-28 21:13:46.000000000 -0400
@@ -34,6 +34,9 @@
 #include "value.h"
 #include "arch-utils.h"
 #include "osabi.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
 
 #include "arm-tdep.h"
 #include "gdb/sim-arm.h"
@@ -155,21 +158,26 @@ static void convert_from_extended (const
 static void convert_to_extended (const struct floatformat *, void *,
 				 const void *);
 
-/* Define other aspects of the stack frame.  We keep the offsets of
-   all saved registers, 'cause we need 'em a lot!  We also keep the
-   current size of the stack frame, and the offset of the frame
-   pointer from the stack pointer (for frameless functions, and when
-   we're still in the prologue of a function with a frame).  */
-
-#define arm_get_cache(fi) ((struct arm_prologue_cache *) get_frame_extra_info (fi))
-
 struct arm_prologue_cache
 {
-  CORE_ADDR unwound_sp, unwound_pc;
+  /* The stack pointer at the time this frame was created; i.e. the
+     caller's stack pointer when this function was called.  It is used
+     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.  */
+
   int framesize;
   int frameoffset;
+
+  /* The register used to hold the frame pointer for this frame.  */
   int framereg;
-  CORE_ADDR saved_regs[1];
+
+  /* Saved register offsets.  */
+  struct trad_frame_saved_reg *saved_regs;
 };
 
 /* Addresses for calling Thumb functions have the bit 0 set.
@@ -178,12 +186,6 @@ struct arm_prologue_cache
 #define MAKE_THUMB_ADDR(addr)	((addr) | 1)
 #define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
 
-static int
-arm_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
-{
-  return (DEPRECATED_FRAME_SAVED_PC (thisframe) >= LOWEST_PC);
-}
-
 /* Set to true if the 32-bit mode is in use.  */
 
 int arm_apcs_32 = 1;
@@ -506,7 +508,6 @@ arm_skip_prologue (CORE_ADDR pc)
      2) which registers are saved on it
      3) the offsets of saved regs
      4) the offset from the stack pointer to the frame pointer
-   This information is stored in the "extra" fields of the frame_info.
 
    A typical Thumb function prologue would create this stack frame
    (offsets relative to FP)
@@ -523,7 +524,7 @@ arm_skip_prologue (CORE_ADDR pc)
 /* *INDENT-ON* */
 
 static void
-thumb_scan_prologue (struct arm_prologue_cache *cache)
+thumb_scan_prologue (CORE_ADDR prev_pc, struct arm_prologue_cache *cache)
 {
   CORE_ADDR prologue_start;
   CORE_ADDR prologue_end;
@@ -538,16 +539,12 @@ thumb_scan_prologue (struct arm_prologue
   int findmask = 0;
   int i;
 
-  /* Don't try to scan dummy frames.  */
-  if (DEPRECATED_PC_IN_CALL_DUMMY (cache->unwound_pc, 0, 0))
-    return;
-
-  if (find_pc_partial_function (cache->unwound_pc, NULL, &prologue_start, &prologue_end))
+  if (find_pc_partial_function (prev_pc, NULL, &prologue_start, &prologue_end))
     {
       struct symtab_and_line sal = find_pc_line (prologue_start, 0);
 
       if (sal.line == 0)		/* no line info, use current PC  */
-	prologue_end = cache->unwound_pc;
+	prologue_end = prev_pc;
       else if (sal.end < prologue_end)	/* next line begins after fn end */
 	prologue_end = sal.end;		/* (probably means no prologue)  */
     }
@@ -556,7 +553,7 @@ thumb_scan_prologue (struct arm_prologue
        16 pushes, an add, and "mv fp,sp".  */
     prologue_end = prologue_start + 40;
 
-  prologue_end = min (prologue_end, cache->unwound_pc);
+  prologue_end = min (prologue_end, prev_pc);
 
   /* Initialize the saved register map.  When register H is copied to
      register L, we will put H in saved_reg[L].  */
@@ -591,7 +588,7 @@ thumb_scan_prologue (struct arm_prologue
 	    if (mask & (1 << regno))
 	      {
 		cache->framesize += 4;
-		cache->saved_regs[saved_reg[regno]] = -cache->framesize;
+		cache->saved_regs[saved_reg[regno]].addr = -cache->framesize;
 		/* Reset saved register map.  */
 		saved_reg[regno] = regno;
 	      }
@@ -708,11 +705,11 @@ thumb_scan_prologue (struct arm_prologue
  */
 
 static void
-arm_scan_prologue (struct arm_prologue_cache *cache)
+arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cache)
 {
   int regno, sp_offset, fp_offset;
-  LONGEST return_value;
   CORE_ADDR prologue_start, prologue_end, current_pc;
+  CORE_ADDR prev_pc = frame_pc_unwind (next_frame);
 
   /* Assume there is no frame until proven otherwise.  */
   cache->framereg = ARM_SP_REGNUM;
@@ -720,15 +717,15 @@ arm_scan_prologue (struct arm_prologue_c
   cache->frameoffset = 0;
 
   /* Check for Thumb prologue.  */
-  if (arm_pc_is_thumb (cache->unwound_pc))
+  if (arm_pc_is_thumb (prev_pc))
     {
-      thumb_scan_prologue (cache);
+      thumb_scan_prologue (prev_pc, cache);
       return;
     }
 
   /* Find the function prologue.  If we can't find the function in
      the symbol table, peek in the stack frame to find the PC.  */
-  if (find_pc_partial_function (cache->unwound_pc, NULL, &prologue_start, &prologue_end))
+  if (find_pc_partial_function (prev_pc, NULL, &prologue_start, &prologue_end))
     {
       /* One way to find the end of the prologue (which works well
          for unoptimized code) is to do the following:
@@ -736,7 +733,7 @@ arm_scan_prologue (struct arm_prologue_c
 	    struct symtab_and_line sal = find_pc_line (prologue_start, 0);
 
 	    if (sal.line == 0)
-	      prologue_end = cache->unwound_pc;
+	      prologue_end = prev_pc;
 	    else if (sal.end < prologue_end)
 	      prologue_end = sal.end;
 
@@ -769,9 +766,16 @@ arm_scan_prologue (struct arm_prologue_c
     }
   else
     {
-      /* Get address of the stmfd in the prologue of the callee; 
-         the saved PC is the address of the stmfd + 8.  */
-      if (!safe_read_memory_integer (cache->unwound_sp, 4,  &return_value))
+      /* We have no symbol information.  Our only option is to assume this
+	 function has a standard stack frame and the normal frame register.
+	 Then, we can find the value of our frame pointer on entrance to
+	 the callee (or at the present moment if this is the innermost frame).
+	 The value stored there should be the address of the stmfd + 8.  */
+      CORE_ADDR frame_loc;
+      LONGEST return_value;
+
+      frame_loc = frame_unwind_register_unsigned (next_frame, ARM_FP_REGNUM);
+      if (!safe_read_memory_integer (frame_loc, 4, &return_value))
         return;
       else
         {
@@ -780,6 +784,9 @@ arm_scan_prologue (struct arm_prologue_c
         }
     }
 
+  if (prev_pc < prologue_end)
+    prologue_end = prev_pc;
+
   /* Now search the prologue looking for instructions that set up the
      frame pointer, adjust the stack pointer, and save registers.
 
@@ -830,7 +837,7 @@ arm_scan_prologue (struct arm_prologue_c
 	    if (mask & (1 << regno))
 	      {
 		sp_offset -= 4;
-		cache->saved_regs[regno] = sp_offset;
+		cache->saved_regs[regno].addr = sp_offset;
 	      }
 	}
       else if ((insn & 0xffffc000) == 0xe54b0000 ||	/* strb rx,[r11,#-n] */
@@ -866,7 +873,7 @@ arm_scan_prologue (struct arm_prologue_c
 	{
 	  sp_offset -= 12;
 	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
-	  cache->saved_regs[regno] = sp_offset;
+	  cache->saved_regs[regno].addr = sp_offset;
 	}
       else if ((insn & 0xffbf0fff) == 0xec2d0200)	/* sfmfd f0, 4, [sp!] */
 	{
@@ -893,7 +900,7 @@ arm_scan_prologue (struct arm_prologue_c
 	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
 	    {
 	      sp_offset -= 12;
-	      cache->saved_regs[fp_start_reg++] = sp_offset;
+	      cache->saved_regs[fp_start_reg++].addr = sp_offset;
 	    }
 	}
       else if ((insn & 0xf0000000) != 0xe0000000)
@@ -916,305 +923,253 @@ arm_scan_prologue (struct arm_prologue_c
     cache->frameoffset = 0;
 }
 
-/* Find REGNUM on the stack.  Otherwise, it's in an active register.
-   One thing we might want to do here is to check REGNUM against the
-   clobber mask, and somehow flag it as invalid if it isn't saved on
-   the stack somewhere.  This would provide a graceful failure mode
-   when trying to get the value of caller-saves registers for an inner
-   frame.  */
-
-static CORE_ADDR
-arm_find_callers_reg (struct frame_info *fi, int regnum)
+static struct arm_prologue_cache *
+arm_make_prologue_cache (struct frame_info *next_frame)
 {
-  /* 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 = get_next_frame (fi))
-    {
-      if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
-	{
-	  return deprecated_read_register_dummy (get_frame_pc (fi),
-						 get_frame_base (fi), regnum);
-	}
-      else if (get_frame_saved_regs (fi)[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 (get_frame_saved_regs (fi)[regnum],
-				      REGISTER_RAW_SIZE (regnum));
-	}
-    }
-  return read_register (regnum);
-}
-/* Function: frame_chain Given a GDB frame, determine the address of
-   the calling function's frame.  This will be used to create a new
-   GDB frame struct, and then DEPRECATED_INIT_EXTRA_FRAME_INFO and
-   DEPRECATED_INIT_FRAME_PC will be called for the new frame.  For
-   ARM, we save the frame size when we initialize the frame_info.  */
+  int reg;
+  struct arm_prologue_cache *cache;
+  CORE_ADDR unwound_fp;
 
-CORE_ADDR
-arm_minimal_frame_chain (struct frame_info *next_frame, struct arm_prologue_cache *cache)
-{
-  CORE_ADDR caller_pc;
-  int framereg = arm_get_cache (next_frame)->framereg;
+  cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (next_frame), 0, 0))
-    return get_frame_base (next_frame);
+  arm_scan_prologue (next_frame, cache);
 
-  if (get_frame_pc (next_frame) < LOWEST_PC)
-    return 0;
+  unwound_fp = frame_unwind_register_unsigned (next_frame, cache->framereg);
+  if (unwound_fp == 0)
+    return cache;
 
-  caller_pc = cache->unwound_pc;
+  cache->prev_sp = unwound_fp + cache->framesize - cache->frameoffset;
 
-  /* If the caller is Thumb and the caller is ARM, or vice versa,
-     the frame register of the caller is different from ours.
-     So we must scan the prologue of the caller to determine its
-     frame register number.  */
-  /* XXX Fixme, we should try to do this without creating a temporary
-     cache!  */
-  /* NOTE drow/2003-06-26: I'm quite suspicious of this code... what is it
-     really doing?  I have the feeling that it's trying to handle the case
-     where my framereg is ARM_FP_REGNUM, and my (Thumb) caller's framereg is
-     THUMB_FP_REGNUM, and switching between the two.  But the unwinder should
-     be taking care of that.  */
-  if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (get_frame_pc (next_frame)))
-    {
-      struct arm_prologue_cache *cache
-	= xcalloc (1, sizeof (struct arm_prologue_cache)
-		   + (NUM_REGS + NUM_PSEUDO_REGS - 1) * sizeof (CORE_ADDR));
-      struct cleanup *old_chain = make_cleanup (xfree, cache);
-
-      /* Now, scan the prologue and obtain the frame register.  */
-      cache->unwound_pc = caller_pc;
-      arm_scan_prologue (cache);
-      framereg = cache->framereg;
-
-      /* Deallocate the storage associated with the temporary frame
-	 created above.  */
-      do_cleanups (old_chain);
-    }
-
-  /* If the caller used a frame register, return its value.
-     Otherwise, return the caller's stack pointer.  */
-  if (framereg == ARM_FP_REGNUM || framereg == THUMB_FP_REGNUM)
-    return arm_find_callers_reg (next_frame, framereg);
-  else
-    /* FIXME drow/2003-06-26: The next frame is an opaque thing at this point,
-       we should only be using frame methods on it.  What if it's a dummy
-       frame, calling a frameless function (framereg == ARM_SP_REGNUM)?  Test
-       it.  */
-    return get_frame_base (next_frame) + arm_get_cache (next_frame)->framesize;
-}
-
-/* This function actually figures out the frame address for a given pc
-   and sp.  This is tricky because we sometimes don't use an explicit
-   frame pointer, and the previous stack pointer isn't necessarily
-   recorded on the stack.  The only reliable way to get this info is
-   to examine the prologue.  */
+  /* Calculate actual addresses of saved registers using offsets
+     determined by arm_scan_prologue.  */
+  for (reg = 0; reg < NUM_REGS; reg++)
+    if (cache->saved_regs[reg].addr != 0)
+      cache->saved_regs[reg].addr += cache->prev_sp;
+
+  return cache;
+}
+
+/* Our frame ID for a normal frame is the current function's starting PC
+   and the caller's SP when we were called.  */
 
 static void
-arm_minimal_frame_info (struct frame_info *next_frame,
-			struct arm_prologue_cache *cache)
+arm_prologue_this_id (struct frame_info *next_frame,
+		      void **this_cache,
+		      struct frame_id *this_id)
 {
-  int reg;
-  CORE_ADDR sp;
+  struct arm_prologue_cache *cache;
+  struct frame_id id;
+  CORE_ADDR func;
 
-  memset (cache->saved_regs, '\000', sizeof (CORE_ADDR) * (NUM_REGS + NUM_PSEUDO_REGS));
+  if (*this_cache == NULL)
+    *this_cache = arm_make_prologue_cache (next_frame);
+  cache = *this_cache;
+
+  func = frame_func_unwind (next_frame);
+
+  /* This is meant to halt the backtrace at "_start".  Make sure we
+     don't halt it at a generic dummy frame. */
+  if (func <= LOWEST_PC || inside_entry_file (func))
+    return;
 
-  /* Compute stack pointer for this frame.  We use this value for both
-     the sigtramp and call dummy cases.  */
+  /* If we've hit a wall, stop.  */
+  if (cache->prev_sp == 0)
+    return;
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (next_frame), 0, 0))
-    /* For generic dummy frames, pull the value direct from the frame.
-       Having an unwind function to do this would be nice.  */
-    sp = deprecated_read_register_dummy (get_frame_pc (next_frame),
-					 get_frame_base (next_frame),
-					 ARM_SP_REGNUM);
-  else if (arm_get_cache (next_frame))
-    sp = (get_frame_base (next_frame)
-	  - arm_get_cache (next_frame)->frameoffset
-	  + arm_get_cache (next_frame)->framesize);
-  else
-    sp = read_sp ();  /* FIXME remove case */
-
-  /* Determine whether or not we're in a sigtramp frame.
-     Unfortunately, it isn't sufficient to test (get_frame_type (fi)
-     == SIGTRAMP_FRAME) because this value is sometimes set after
-     invoking DEPRECATED_INIT_EXTRA_FRAME_INFO.  So we test *both*
-     (get_frame_type (fi) == SIGTRAMP_FRAME) and PC_IN_SIGTRAMP to
-     determine if we need to use the sigcontext addresses for the
-     saved registers.
+  id = frame_id_build (cache->prev_sp, func);
 
-     Note: If an ARM PC_IN_SIGTRAMP method ever needs to compare
-     against the name of the function, the code below will have to be
-     changed to first fetch the name of the function and then pass
-     this name to PC_IN_SIGTRAMP.  */
+  /* Check that we're not going round in circles with the same frame
+     ID (but avoid applying the test to sentinel frames which do go
+     round in circles).  */
+  if (frame_relative_level (next_frame) >= 0
+      && get_frame_type (next_frame) == NORMAL_FRAME
+      && frame_id_eq (get_frame_id (next_frame), id))
+    return;
 
-  /* FIXME: cagney/2002-11-18: This problem will go away once
-     frame.c:get_prev_frame() is modified to set the frame's type
-     before calling functions like this.  */
-
-  /* NOTE drow/2003-06-26: This will move to a predicate for a different unwinder shortly.  */
-
-  if (SIGCONTEXT_REGISTER_ADDRESS_P () 
-      && PC_IN_SIGTRAMP (cache->unwound_pc, (char *)0))
-    {
-      for (reg = 0; reg < NUM_REGS; reg++)
-	cache->saved_regs[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, cache->unwound_pc, reg);
-
-      /* FIXME: What about thumb mode?  */
-      cache->framereg = ARM_SP_REGNUM;
-      cache->unwound_sp = read_memory_integer (cache->saved_regs[cache->framereg], REGISTER_RAW_SIZE (cache->framereg));
-      cache->framesize = 0;
-      cache->frameoffset = 0;
-    }
-  else
-    {
-      /* At this point, the unwound sp is just the result of frame_chain.
-	 Then it gets changed below.  */
-
-      arm_scan_prologue (cache);
-
-      if (!next_frame)
-	/* This is the innermost frame?  */
-	cache->unwound_sp = read_register (cache->framereg);
-      else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (next_frame), 0, 0))
-	/* Next inner most frame is a dummy, just grab its frame.
-           Dummy frames always have the same FP as their caller.  */
-	cache->unwound_sp = get_frame_base (next_frame);
-      else if (cache->framereg == ARM_FP_REGNUM
-	       || cache->framereg == THUMB_FP_REGNUM)
-	{
-	  /* not the innermost frame */
-	  /* If we have an FP, the callee saved it.  */
-	  if (get_frame_saved_regs (next_frame) /**/ && get_frame_saved_regs (next_frame)[cache->framereg] != 0)
-	    cache->unwound_sp = read_memory_integer (get_frame_saved_regs (next_frame)[cache->framereg], 4);
-	  else if (frame_relative_level (next_frame) == 0
-		   && FRAMELESS_FUNCTION_INVOCATION (next_frame))
-	    /* If we were called by a frameless fn.  then our frame is
-	       still in the frame pointer register on the board...  */
-	    cache->unwound_sp = deprecated_read_fp ();
-	}
-
-      /* Calculate actual addresses of saved registers using offsets
-         determined by arm_scan_prologue.  */
-      for (reg = 0; reg < NUM_REGS; reg++)
-	if (cache->saved_regs[reg] != 0)
-	  cache->saved_regs[reg] = (cache->saved_regs[reg]
-				    + cache->unwound_sp
-				    + cache->framesize
-				    - cache->frameoffset);
-    }
+  *this_id = id;
 }
 
-static struct arm_prologue_cache *
-arm_make_prologue_cache (struct frame_info *next_frame)
+static void
+arm_prologue_prev_register (struct frame_info *next_frame,
+			    void **this_cache,
+			    int prev_regnum,
+			    int *optimized,
+			    enum lval_type *lvalp,
+			    CORE_ADDR *addrp,
+			    int *realnump,
+			    void *valuep)
 {
   struct arm_prologue_cache *cache;
 
-  cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache)
-				+ sizeof (CORE_ADDR) * (NUM_REGS + NUM_PSEUDO_REGS - 1));
+  if (*this_cache == NULL)
+    *this_cache = arm_make_prologue_cache (next_frame);
+  cache = *this_cache;
+
+  /* If we are asked to unwind the PC, then we need to return the LR
+     instead.  The saved value of PC points into this frame's
+     prologue, not the next frame's resume location.  */
+  if (prev_regnum == ARM_PC_REGNUM)
+    prev_regnum = ARM_LR_REGNUM;
+
+  /* SP is generally not saved to the stack, but this frame is
+     identified by NEXT_FRAME's stack pointer at the time of the call.
+     The value was already reconstructed into PREV_SP.  */
+  if (prev_regnum == ARM_SP_REGNUM)
+    {
+      *lvalp = not_lval;
+      if (valuep)
+	store_unsigned_integer (valuep, 4, cache->prev_sp);
+      return;
+    }
 
-  cache->unwound_pc = frame_pc_unwind (next_frame);
-  if (frame_relative_level (next_frame) < 0)
-    cache->unwound_sp = deprecated_read_fp ();
-  else
-    cache->unwound_sp = arm_minimal_frame_chain (next_frame, cache);
-  arm_minimal_frame_info (next_frame, cache);
+  trad_frame_prev_register (next_frame, cache->saved_regs, prev_regnum,
+			    optimized, lvalp, addrp, realnump, valuep);
+}
 
-  return cache;
+struct frame_unwind arm_prologue_unwind = {
+  NORMAL_FRAME,
+  arm_prologue_this_id,
+  arm_prologue_prev_register
+};
+
+static const struct frame_unwind *
+arm_prologue_unwind_sniffer (struct frame_info *next_frame)
+{
+  return &arm_prologue_unwind;
 }
 
 static CORE_ADDR
-arm_frame_chain (struct frame_info *next_frame)
+arm_normal_frame_base (struct frame_info *next_frame, void **this_cache)
 {
   struct arm_prologue_cache *cache;
 
-  cache = arm_make_prologue_cache (next_frame);
-  return cache->unwound_sp;
+  if (*this_cache == NULL)
+    *this_cache = arm_make_prologue_cache (next_frame);
+  cache = *this_cache;
+
+  return cache->prev_sp + cache->frameoffset - cache->framesize;
 }
 
-static void
-arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+struct frame_base arm_normal_base = {
+  &arm_prologue_unwind,
+  arm_normal_frame_base,
+  arm_normal_frame_base,
+  arm_normal_frame_base
+};
+
+static struct arm_prologue_cache *
+arm_make_sigtramp_cache (struct frame_info *next_frame)
 {
   struct arm_prologue_cache *cache;
+  int reg;
 
-  cache = arm_make_prologue_cache (deprecated_get_next_frame_hack (fi));
+  cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
 
-  if (get_frame_saved_regs (fi) == NULL)
-    frame_saved_regs_zalloc (fi);
+  cache->prev_sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
 
-  frame_extra_info_zalloc (fi, (sizeof (struct arm_prologue_cache)
-				+ ((NUM_REGS + NUM_PSEUDO_REGS - 1)
-				   * sizeof (CORE_ADDR))));
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
-  memcpy (get_frame_extra_info (fi), cache,  (sizeof (struct arm_prologue_cache)
-					      + ((NUM_REGS + NUM_PSEUDO_REGS - 1)
-						 * sizeof (CORE_ADDR))));
-  memcpy (get_frame_saved_regs (fi), cache->saved_regs,
-	  (NUM_REGS + NUM_PSEUDO_REGS - 1) * sizeof (CORE_ADDR));
+  for (reg = 0; reg < NUM_REGS; reg++)
+    cache->saved_regs[reg].addr
+      = SIGCONTEXT_REGISTER_ADDRESS (cache->prev_sp,
+				     frame_pc_unwind (next_frame), reg);
+
+  /* FIXME: What about thumb mode?  */
+  cache->framereg = ARM_SP_REGNUM;
+  cache->prev_sp
+    = read_memory_integer (cache->saved_regs[cache->framereg].addr,
+			   REGISTER_RAW_SIZE (cache->framereg));
+
+  return cache;
 }
 
-/* Find the caller of this frame.  We do this by seeing if ARM_LR_REGNUM
-   is saved in the stack anywhere, otherwise we get it from the
-   registers.
+static void
+arm_sigtramp_this_id (struct frame_info *next_frame,
+		      void **this_cache,
+		      struct frame_id *this_id)
+{
+  struct arm_prologue_cache *cache;
 
-   The old definition of this function was a macro:
-   #define FRAME_SAVED_PC(FRAME) \
-   ADDR_BITS_REMOVE (read_memory_integer ((FRAME)->frame - 4, 4)) */
+  if (*this_cache == NULL)
+    *this_cache = arm_make_sigtramp_cache (next_frame);
+  cache = *this_cache;
+
+  /* FIXME drow/2003-07-07: This isn't right if we single-step within
+     the sigtramp frame; the PC should be the beginning of the trampoline.  */
+  *this_id = frame_id_build (cache->prev_sp, frame_pc_unwind (next_frame));
+}
 
-static CORE_ADDR
-arm_frame_saved_pc (struct frame_info *fi)
+static void
+arm_sigtramp_prev_register (struct frame_info *next_frame,
+			    void **this_cache,
+			    int prev_regnum,
+			    int *optimized,
+			    enum lval_type *lvalp,
+			    CORE_ADDR *addrp,
+			    int *realnump,
+			    void *valuep)
 {
-  /* If a dummy frame, pull the PC out of the frame's register buffer.  */
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
-    return deprecated_read_register_dummy (get_frame_pc (fi),
-					   get_frame_base (fi), ARM_PC_REGNUM);
+  struct arm_prologue_cache *cache;
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi),
-				   (get_frame_base (fi)
-				    - arm_get_cache (fi)->frameoffset),
-				   get_frame_base (fi)))
-    {
-      return read_memory_integer (get_frame_saved_regs (fi)[ARM_PC_REGNUM],
-				  REGISTER_RAW_SIZE (ARM_PC_REGNUM));
-    }
-  else
-    {
-      CORE_ADDR pc = arm_find_callers_reg (fi, ARM_LR_REGNUM);
-      return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
-    }
+  if (*this_cache == NULL)
+    *this_cache = arm_make_sigtramp_cache (next_frame);
+  cache = *this_cache;
+
+  trad_frame_prev_register (next_frame, cache->saved_regs, prev_regnum,
+			    optimized, lvalp, addrp, realnump, valuep);
 }
 
-/* Return the frame address.  On ARM, it is R11; on Thumb it is R7.
-   Examine the Program Status Register to decide which state we're in.  */
+struct frame_unwind arm_sigtramp_unwind = {
+  SIGTRAMP_FRAME,
+  arm_sigtramp_this_id,
+  arm_sigtramp_prev_register
+};
 
-static CORE_ADDR
-arm_read_fp (void)
+static const struct frame_unwind *
+arm_sigtramp_unwind_sniffer (struct frame_info *next_frame)
 {
-  if (read_register (ARM_PS_REGNUM) & 0x20)	/* Bit 5 is Thumb state bit */
-    return read_register (THUMB_FP_REGNUM);	/* R7 if Thumb */
-  else
-    return read_register (ARM_FP_REGNUM);	/* R11 if ARM */
+  /* Note: If an ARM PC_IN_SIGTRAMP method ever needs to compare
+     against the name of the function, the code below will have to be
+     changed to first fetch the name of the function and then pass
+     this name to PC_IN_SIGTRAMP.  */
+
+  if (SIGCONTEXT_REGISTER_ADDRESS_P ()
+      && PC_IN_SIGTRAMP (frame_pc_unwind (next_frame), (char *) 0))
+    return &arm_sigtramp_unwind;
+
+  return NULL;
 }
 
-/* Store into a struct frame_saved_regs the addresses of the saved
-   registers of frame described by FRAME_INFO.  This includes special
-   registers such as PC and FP saved in special ways in the stack
-   frame.  SP is even more special: the address we return for it IS
-   the sp for the next frame.  */
+/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+   dummy frame.  The frame ID's base needs to match the TOS value
+   saved by save_dummy_frame_tos() and returned from
+   arm_push_dummy_call, and the PC needs to match the dummy frame's
+   breakpoint.  */
 
-static void
-arm_frame_init_saved_regs (struct frame_info *fip)
+static struct frame_id
+arm_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
+  return frame_id_build (frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM),
+			 frame_pc_unwind (next_frame));
+}
 
-  if (get_frame_saved_regs (fip))
-    return;
+/* Given THIS_FRAME, find the previous frame's resume PC (which will
+   be used to construct the previous frame's ID, after looking up the
+   containing function).  */
+
+static CORE_ADDR
+arm_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+  CORE_ADDR pc;
+  pc = frame_unwind_register_unsigned (this_frame, ARM_PC_REGNUM);
+  return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
+}
 
-  arm_init_extra_frame_info (0, fip);
+static CORE_ADDR
+arm_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+  return frame_unwind_register_unsigned (this_frame, ARM_SP_REGNUM);
 }
 
 /* Set the return address for a generic dummy frame.  ARM uses the
@@ -1359,40 +1314,6 @@ arm_fix_call_dummy (char *dummy, CORE_AD
   write_register (4, fun);
 }
 
-/* Pop the current frame.  So long as the frame info has been
-   initialized properly (see arm_init_extra_frame_info), this code
-   works for dummy frames as well as regular frames.  I.e, there's no
-   need to have a special case for dummy frames.  */
-static void
-arm_pop_frame (void)
-{
-  int regnum;
-  struct frame_info *frame = get_current_frame ();
-  CORE_ADDR old_SP = (get_frame_base (frame)
-		      - arm_get_cache (frame)->frameoffset
-		      + arm_get_cache (frame)->framesize);
-
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
-				   get_frame_base (frame),
-				   get_frame_base (frame)))
-    {
-      generic_pop_dummy_frame ();
-      flush_cached_frames ();
-      return;
-    }
-
-  for (regnum = 0; regnum < NUM_REGS; regnum++)
-    if (get_frame_saved_regs (frame)[regnum] != 0)
-      write_register (regnum,
-		  read_memory_integer (get_frame_saved_regs (frame)[regnum],
-				       REGISTER_RAW_SIZE (regnum)));
-
-  write_register (ARM_PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame));
-  write_register (ARM_SP_REGNUM, old_SP);
-
-  flush_cached_frames ();
-}
-
 /* When arguments must be pushed onto the stack, they go on in reverse
    order.  The code below implements a FILO (stack) to do this.  */
 
@@ -2873,10 +2794,6 @@ arm_gdbarch_init (struct gdbarch_info in
   tdep = xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
-     ready to unwind the PC first (see frame.c:get_prev_frame()).  */
-  set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
-
   /* We used to default to FPA for generic ARM, but almost nobody uses that
      now, and we now provide a way for the user to force the model.  So 
      default to the most useful variant.  */
@@ -2919,16 +2836,15 @@ arm_gdbarch_init (struct gdbarch_info in
   set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call);
 
   /* Frame handling.  */
-  set_gdbarch_deprecated_frame_chain_valid (gdbarch, arm_frame_chain_valid);
-  set_gdbarch_deprecated_init_extra_frame_info (gdbarch, arm_init_extra_frame_info);
-  set_gdbarch_deprecated_target_read_fp (gdbarch, arm_read_fp);
-  set_gdbarch_deprecated_frame_chain (gdbarch, arm_frame_chain);
+  set_gdbarch_unwind_dummy_id (gdbarch, arm_unwind_dummy_id);
+  set_gdbarch_unwind_pc (gdbarch, arm_unwind_pc);
+  set_gdbarch_unwind_sp (gdbarch, arm_unwind_sp);
+
   set_gdbarch_frameless_function_invocation
     (gdbarch, arm_frameless_function_invocation);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, arm_frame_saved_pc);
   set_gdbarch_frame_args_skip (gdbarch, 0);
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, arm_frame_init_saved_regs);
-  set_gdbarch_deprecated_pop_frame (gdbarch, arm_pop_frame);
+
+  frame_base_set_default (gdbarch, &arm_normal_base);
 
   /* Address manipulation.  */
   set_gdbarch_smash_text_address (gdbarch, arm_smash_text_address);
@@ -2996,6 +2912,10 @@ arm_gdbarch_init (struct gdbarch_info in
   /* Hook in the ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
+  /* Add some default predicates.  */
+  frame_unwind_append_sniffer (gdbarch, arm_sigtramp_unwind_sniffer);
+  frame_unwind_append_sniffer (gdbarch, arm_prologue_unwind_sniffer);
+
   /* Now we have tuned the configuration, set a few final things,
      based on what the OS ABI has told us.  */
 
Index: gdb/Makefile.in
===================================================================
--- gdb.orig/Makefile.in	2003-08-28 21:13:42.000000000 -0400
+++ gdb/Makefile.in	2003-08-28 21:13:46.000000000 -0400
@@ -1586,7 +1586,8 @@ arm-tdep.o: arm-tdep.c $(defs_h) $(frame
 	$(gdbcore_h) $(symfile_h) $(gdb_string_h) $(dis_asm_h) $(regcache_h) \
 	$(doublest_h) $(value_h) $(arch_utils_h) $(osabi_h) $(arm_tdep_h) \
 	$(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) $(elf_arm_h) \
-	$(gdb_assert_h) $(bfd_in2_h) $(libcoff_h)
+	$(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) $(frame_unwind_h) \
+	$(trad_frame_h) $(frame_base_h)
 avr-tdep.o: avr-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
 	$(frame_base_h) $(trad_frame_h) $(gdbcmd_h) $(gdbcore_h) \
 	$(inferior_h) $(symfile_h) $(arch_utils_h) $(regcache_h) \
Index: gdb/varobj.c
===================================================================
--- gdb.orig/varobj.c	2003-08-28 21:13:42.000000000 -0400
+++ gdb/varobj.c	2003-08-28 21:13:46.000000000 -0400
@@ -412,7 +412,7 @@ find_frame_addr_in_frame_chain (CORE_ADD
       frame = get_prev_frame (frame);
       if (frame == NULL)
 	return NULL;
-      if (get_frame_base (frame) == frame_addr)
+      if (get_frame_base_address (frame) == frame_addr)
 	return frame;
     }
 }
Index: gdb/std-regs.c
===================================================================
--- gdb.orig/std-regs.c	2003-08-28 21:13:42.000000000 -0400
+++ gdb/std-regs.c	2003-08-28 21:13:46.000000000 -0400
@@ -90,7 +90,7 @@ value_of_builtin_frame_fp_reg (struct fr
 	memset (buf, TYPE_LENGTH (VALUE_TYPE (val)), 0);
       else
 	ADDRESS_TO_POINTER (builtin_type_void_data_ptr, buf,
-			    get_frame_base (frame));
+			    get_frame_base_address (frame));
       return val;
     }
 }
-------------- next part --------------
2003-08-28  Daniel Jacobowitz  <drow@mvista.com>

	* arm-tdep.c: Include "dwarf2-frame.h".
	(arm_gdbarch_init): Use dwarf2_frame_sniffer.
	* Makefile.in (arm-tdep.o): Update dependencies.

Index: gdb/arm-tdep.c
===================================================================
--- gdb.orig/arm-tdep.c	2003-08-28 21:13:46.000000000 -0400
+++ gdb/arm-tdep.c	2003-08-28 21:13:46.000000000 -0400
@@ -37,6 +37,7 @@
 #include "frame-unwind.h"
 #include "frame-base.h"
 #include "trad-frame.h"
+#include "dwarf2-frame.h"
 
 #include "arm-tdep.h"
 #include "gdb/sim-arm.h"
@@ -2912,8 +2913,15 @@ arm_gdbarch_init (struct gdbarch_info in
   /* Hook in the ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  /* Add some default predicates.  */
+  /* Add some default frame sniffers.  */
+
   frame_unwind_append_sniffer (gdbarch, arm_sigtramp_unwind_sniffer);
+
+  /* Hook in the DWARF CFI frame unwinder.  We do not use dwarf2 for frame
+     bases because it has the crazy idea that the frame base should be the
+     CFA.  */
+  frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+
   frame_unwind_append_sniffer (gdbarch, arm_prologue_unwind_sniffer);
 
   /* Now we have tuned the configuration, set a few final things,
Index: gdb/Makefile.in
===================================================================
--- gdb.orig/Makefile.in	2003-08-28 21:13:46.000000000 -0400
+++ gdb/Makefile.in	2003-08-28 21:13:46.000000000 -0400
@@ -1587,7 +1587,7 @@ arm-tdep.o: arm-tdep.c $(defs_h) $(frame
 	$(doublest_h) $(value_h) $(arch_utils_h) $(osabi_h) $(arm_tdep_h) \
 	$(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) $(elf_arm_h) \
 	$(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) $(frame_unwind_h) \
-	$(trad_frame_h) $(frame_base_h)
+	$(trad_frame_h) $(frame_base_h) $(dwarf2_frame_h)
 avr-tdep.o: avr-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
 	$(frame_base_h) $(trad_frame_h) $(gdbcmd_h) $(gdbcore_h) \
 	$(inferior_h) $(symfile_h) $(arch_utils_h) $(regcache_h) \


More information about the Gdb-patches mailing list