Prologue scanner modifications.
authorKevin Buettner <kevinb@redhat.com>
Fri, 1 Jun 2001 02:39:51 +0000 (02:39 +0000)
committerKevin Buettner <kevinb@redhat.com>
Fri, 1 Jun 2001 02:39:51 +0000 (02:39 +0000)
gdb/ChangeLog
gdb/ia64-tdep.c

index 5b02069..0667b8b 100644 (file)
@@ -4,6 +4,13 @@
        match the location at which the kernel is placing the sigcontext
        struct.
 
+       * 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.
+
 2001-05-29  Christopher Faylor  <cgf@redhat.com>
 
        * partial-stab.h: Revert previous patch.
index 2a1b351..afa0e1c 100644 (file)
@@ -717,6 +717,69 @@ ia64_frame_saved_pc (struct frame_info *frame)
     }
 }
 
+/* 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_ADDR lim_pc, struct frame_info *frame)
   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_ADDR lim_pc, struct frame_info *frame)
       && 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_ADDR lim_pc, struct frame_info *frame)
       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. */