This is the mail archive of the gdb-patches@sources.redhat.com 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]

[PATCH] ia64-tdep.c: prologue scanner refinements


I've just committed the patch below.  It makes examine_prologue() do a
better job of returning the actual end of prologue for frameless
functions.  This eliminates over one hundred FAILs for
ia64-unknown-linux.  In addition, the new function
refine_prologue_limit() will make prologue scanning somewhat more
efficient since fewer instructions will be scanned.

	* ia64-tdep.c (max_skip_non_prologue_insns): New static global.
	(refine_prologue_limit): New function.
	(examine_prologue):  Further limit number of instructions
	scanned by calling refine_prologue_limit().  Revise way in
	which the end of prologue address is computed for frameless
	functions.

Index: ia64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ia64-tdep.c,v
retrieving revision 1.18
diff -u -p -r1.18 ia64-tdep.c
--- ia64-tdep.c	2001/05/04 04:15:25	1.18
+++ ia64-tdep.c	2001/06/01 02:33:01
@@ -717,6 +717,69 @@ ia64_frame_saved_pc (struct frame_info *
     }
 }
 
+/* Limit the number of skipped non-prologue instructions since examining
+   of the prologue is expensive.  */
+static int max_skip_non_prologue_insns = 10;
+
+/* Given PC representing the starting address of a function, and
+   LIM_PC which is the (sloppy) limit to which to scan when looking
+   for a prologue, attempt to further refine this limit by using
+   the line data in the symbol table.  If successful, a better guess
+   on where the prologue ends is returned, otherwise the previous
+   value of lim_pc is returned.  TRUST_LIMIT is a pointer to a flag
+   which will be set to indicate whether the returned limit may be
+   used with no further scanning in the event that the function is
+   frameless.  */
+
+static CORE_ADDR
+refine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc, int *trust_limit)
+{
+  struct symtab_and_line prologue_sal;
+  CORE_ADDR start_pc = pc;
+
+  /* Start off not trusting the limit.  */
+  *trust_limit = 0;
+
+  prologue_sal = find_pc_line (pc, 0);
+  if (prologue_sal.line != 0)
+    {
+      int i;
+      CORE_ADDR addr = prologue_sal.end;
+
+      /* Handle the case in which compiler's optimizer/scheduler
+         has moved instructions into the prologue.  We scan ahead
+	 in the function looking for address ranges whose corresponding
+	 line number is less than or equal to the first one that we
+	 found for the function.  (It can be less than when the
+	 scheduler puts a body instruction before the first prologue
+	 instruction.)  */
+      for (i = 2 * max_skip_non_prologue_insns; 
+           i > 0 && (lim_pc == 0 || addr < lim_pc);
+	   i--)
+        {
+	  struct symtab_and_line sal;
+
+	  sal = find_pc_line (addr, 0);
+	  if (sal.line == 0)
+	    break;
+	  if (sal.line <= prologue_sal.line 
+	      && sal.symtab == prologue_sal.symtab)
+	    {
+	      prologue_sal = sal;
+	    }
+	  addr = sal.end;
+	}
+
+      if (lim_pc == 0 || prologue_sal.end < lim_pc)
+	{
+	  lim_pc = prologue_sal.end;
+	  if (start_pc == get_pc_function_start (lim_pc))
+	    *trust_limit = 1;
+	}
+    }
+  return lim_pc;
+}
+
 #define isScratch(_regnum_) ((_regnum_) == 2 || (_regnum_) == 3 \
   || (8 <= (_regnum_) && (_regnum_) <= 11) \
   || (14 <= (_regnum_) && (_regnum_) <= 31))
@@ -744,6 +807,7 @@ examine_prologue (CORE_ADDR pc, CORE_ADD
   CORE_ADDR spill_addr = 0;
   char instores[8];
   char infpstores[8];
+  int trust_limit;
 
   memset (instores, 0, sizeof instores);
   memset (infpstores, 0, sizeof infpstores);
@@ -760,6 +824,8 @@ examine_prologue (CORE_ADDR pc, CORE_ADD
       && frame->extra_info->after_prologue <= lim_pc)
     return frame->extra_info->after_prologue;
 
+  lim_pc = refine_prologue_limit (pc, lim_pc, &trust_limit);
+
   /* Must start with an alloc instruction */
   next_pc = fetch_instruction (pc, &it, &instr);
   if (pc < lim_pc && next_pc 
@@ -779,7 +845,11 @@ examine_prologue (CORE_ADDR pc, CORE_ADD
       pc = next_pc;
     }
   else
-    pc = lim_pc;	/* We're done early */
+    {
+      pc = lim_pc;	/* Frameless: We're done early.  */
+      if (trust_limit)
+	last_prologue_pc = lim_pc;
+    }
 
   /* Loop, looking for prologue instructions, keeping track of
      where preserved registers were spilled. */


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