* rs6000-tdep.c (rs6000_skip_prologue): Use skip_prologue_using_sal.
authorDaniel Jacobowitz <drow@false.org>
Tue, 13 Mar 2007 17:34:23 +0000 (17:34 +0000)
committerDaniel Jacobowitz <drow@false.org>
Tue, 13 Mar 2007 17:34:23 +0000 (17:34 +0000)
(rs6000_in_function_epilogue_p): Use extract_unsigned_integer.
(refine_prologue_limit): Delete.
(skip_prologue): Don't call it.  Use extract_unsigned_integer.
Assume lim_pc is set.  Correct check for incomplete prologues.
Do not skip clobbers of the frame pointer.
* symtab.c (skip_prologue_using_sal): Fail if there is only one
sal.

* gdb.arch/powerpc-prologue.c (optimized_1_marker, gdb2029_marker)
(optimized_1): New.
(main): Call optimized_1.
(gdb2029): Correct typos.  Call gdb2029_marker.
* gdb.arch/powerpc-prologue.exp: Run new test.  Use a breakpoint
for gdb2029.

gdb/ChangeLog
gdb/rs6000-tdep.c
gdb/symtab.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/powerpc-prologue.c
gdb/testsuite/gdb.arch/powerpc-prologue.exp

index 3766bc1643e560a59eed2b609074861800500540..8624df056fabae15d6ccb886ebc1c9d24b84321f 100644 (file)
@@ -1,3 +1,14 @@
+2007-03-13  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * rs6000-tdep.c (rs6000_skip_prologue): Use skip_prologue_using_sal.
+       (rs6000_in_function_epilogue_p): Use extract_unsigned_integer.
+       (refine_prologue_limit): Delete.
+       (skip_prologue): Don't call it.  Use extract_unsigned_integer.
+       Assume lim_pc is set.  Correct check for incomplete prologues.
+       Do not skip clobbers of the frame pointer.
+       * symtab.c (skip_prologue_using_sal): Fail if there is only one
+       sal.
+
 2007-03-13  Nathan Froyd  <froydnj@codesourcery.com>
 
        * frame.c (frame_pop): Check to see whether there's a frame to
index 25fa5508f6438a3c052f90cd1f32c51625e0d1a2..cc2f074121b9a9d3cb6fde0d93a544c6beb0b6d0 100644 (file)
@@ -482,7 +482,29 @@ static CORE_ADDR
 rs6000_skip_prologue (CORE_ADDR pc)
 {
   struct rs6000_framedata frame;
-  pc = skip_prologue (pc, 0, &frame);
+  CORE_ADDR limit_pc, func_addr;
+
+  /* See if we can determine the end of the prologue via the symbol table.
+     If so, then return either PC, or the PC after the prologue, whichever
+     is greater.  */
+  if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+    {
+      CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+      if (post_prologue_pc != 0)
+       return max (pc, post_prologue_pc);
+    }
+
+  /* Can't determine prologue from the symbol table, need to examine
+     instructions.  */
+
+  /* Find an upper limit on the function prologue using the debug
+     information.  If the debug information could not be used to provide
+     that bound, then use an arbitrary large number as the upper bound.  */
+  limit_pc = skip_prologue_using_sal (pc);
+  if (limit_pc == 0)
+    limit_pc = pc + 100;          /* Magic.  */
+
+  pc = skip_prologue (pc, limit_pc, &frame);
   return pc;
 }
 
@@ -565,7 +587,7 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
         return 0;
-      insn = extract_signed_integer (insn_buf, PPC_INSN_SIZE);
+      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
       if (insn == 0x4e800020)
         break;
       if (insn_changes_sp_or_jumps (insn))
@@ -580,7 +602,7 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
         return 0;
-      insn = extract_signed_integer (insn_buf, PPC_INSN_SIZE);
+      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
       if (insn_changes_sp_or_jumps (insn))
         return 1;
     }
@@ -775,57 +797,6 @@ rs6000_software_single_step (enum target_signal signal,
    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.  */
-
-/* FIXME: cagney/2004-02-14: This function and logic have largely been
-   superseded by skip_prologue_using_sal.  */
-
-static CORE_ADDR
-refine_prologue_limit (CORE_ADDR pc, CORE_ADDR lim_pc)
-{
-  struct symtab_and_line prologue_sal;
-
-  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;
-    }
-  return lim_pc;
-}
-
 /* Return nonzero if the given instruction OP can be part of the prologue
    of a function and saves a parameter on the stack.  FRAMEP should be
    set if one of the previous instructions in the function has set the
@@ -945,21 +916,6 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
   int r0_contains_arg = 0;
   const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch);
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  
-  /* Attempt to find the end of the prologue when no limit is specified.
-     Note that refine_prologue_limit() has been written so that it may
-     be used to "refine" the limits of non-zero PC values too, but this
-     is only safe if we 1) trust the line information provided by the
-     compiler and 2) iterate enough to actually find the end of the
-     prologue.  
-     
-     It may become a good idea at some point (for both performance and
-     accuracy) to unconditionally call refine_prologue_limit().  But,
-     until we can make a clear determination that this is beneficial,
-     we'll play it safe and only use it to obtain a limit when none
-     has been specified.  */
-  if (lim_pc == 0)
-    lim_pc = refine_prologue_limit (pc, lim_pc);
 
   memset (fdata, 0, sizeof (struct rs6000_framedata));
   fdata->saved_gpr = -1;
@@ -980,7 +936,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
        last_prologue_pc = pc;
 
       /* Stop scanning if we've hit the limit.  */
-      if (lim_pc != 0 && pc >= lim_pc)
+      if (pc >= lim_pc)
        break;
 
       prev_insn_was_prologue_insn = 1;
@@ -988,7 +944,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
       /* Fetch the instruction and convert it to an integer.  */
       if (target_read_memory (pc, buf, 4))
        break;
-      op = extract_signed_integer (buf, 4);
+      op = extract_unsigned_integer (buf, 4);
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
        {                       /* mflr Rx */
@@ -1221,9 +1177,11 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
          offset = fdata->offset;
          continue;
        }
-      /* Load up minimal toc pointer */
+      /* Load up minimal toc pointer.  Do not treat an epilogue restore
+        of r31 as a minimal TOC load.  */
       else if (((op >> 22) == 0x20f    ||      /* l r31,... or l r30,... */
               (op >> 22) == 0x3af)             /* ld r31,... or ld r30,... */
+              && !framep
               && !minimal_toc_loaded)
        {
          minimal_toc_loaded = 1;
@@ -1446,8 +1404,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
             Handle optimizer code motions into the prologue by continuing
             the search if we have no valid frame yet or if the return
             address is not yet saved in the frame.  */
-         if (fdata->frameless == 0
-             && (lr_reg == -1 || fdata->nosavedpc == 0))
+         if (fdata->frameless == 0 && fdata->nosavedpc == 0)
            break;
 
          if (op == 0x4e800020          /* blr */
index f12834dd1cd12131643613855484f9b9147eeee7..c427c98637ada1fb33d962c94e0e3fe400c03be4 100644 (file)
@@ -4092,7 +4092,7 @@ skip_prologue_using_sal (CORE_ADDR func_addr)
         then it is probably a single line function, like
         "foo(){}". */
       if (prologue_sal.end == end_pc)
-       return start_pc;
+       return 0;
       while (prologue_sal.end < end_pc)
        {
          struct symtab_and_line sal;
index 9300ec35b4f083a44fbbc391608c6bfdd72bdc63..bfa0b8758af2ca64f0e6c66e6f29df66803bf654 100644 (file)
@@ -1,3 +1,12 @@
+2007-03-13  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.arch/powerpc-prologue.c (optimized_1_marker, gdb2029_marker)
+       (optimized_1): New.
+       (main): Call optimized_1.
+       (gdb2029): Correct typos.  Call gdb2029_marker.
+       * gdb.arch/powerpc-prologue.exp: Run new test.  Use a breakpoint
+       for gdb2029.
+
 2007-03-12  Mark Kettenis  <kettenis@gnu.org>
 
        * gdb.gdb/selftest.exp (do_steps_and_nexts): Match spaces as well
index 9f3836a6d6a69b8fcdc92fcc39fb2a704a85d523..6dcec2fcf63bdfd2ea85f75cfdd930d7a38c916b 100644 (file)
@@ -31,23 +31,54 @@ int
 main (void)
 {
   gdb2029 ();
+  optimized_1 ();
   return 0;
 }
 
+void
+optimized_1_marker (void)
+{
+}
+
+void
+gdb2029_marker (void)
+{
+}
+
 /* A typical PIC prologue from GCC.  */
 
 asm(".text\n"
-    "    .align 8\n"
+    "    .p2align 3\n"
     SYMBOL (gdb2029) ":\n"
-    "  stw     %r1, -32(%r1)\n"
+    "  stwu    %r1, -32(%r1)\n"
     "  mflr    %r0\n"
     "  bcl-    20,31,.+4\n"
     "  stw     %r30, 24(%r1)\n"
     "  mflr    %r30\n"
     "  stw     %r0, 36(%r1)\n"
-    "  twge    %r2, %r2\n"
+    "  bl      gdb2029_marker\n"
     "  lwz     %r0, 36(%r1)\n"
     "  lwz     %r30, 24(%r1)\n"
     "  mtlr    %r0\n"
-    "  addi    %r0, %r0, 32\n"
+    "  addi    %r1, %r1, 32\n"
+    "  blr");
+
+/* A heavily scheduled prologue.  */
+asm(".text\n"
+    "  .p2align 3\n"
+    SYMBOL (optimized_1) ":\n"
+    "  stwu    %r1,-32(%r1)\n"
+    "  lis     %r9,-16342\n"
+    "  lis     %r11,-16342\n"
+    "  mflr    %r0\n"
+    "  addi    %r11,%r11,3776\n"
+    "  stmw    %r27,12(%r1)\n"
+    "  addi    %r31,%r9,3152\n"
+    "  cmplw   %cr7,%r31,%r11\n"
+    "  stw     %r0,36(%r1)\n"
+    "  mr      %r30,%r3\n"
+    "  bl      optimized_1_marker\n"
+    "  lwz     %r0,36(%r1)\n"
+    "  lmw     %r27,12(%r1)\n"
+    "  addi    %r1,%r1,32\n"
     "  blr");
index c50c56bb029ddff8a13b1e7b18f900b2a5d10c9d..9bacb9997e8c207648008a3fc68b66c4149cc32a 100644 (file)
@@ -50,12 +50,40 @@ if ![runto_main] then {
 
 # Testcase for PIC prologue.
 
-gdb_test "continue" "Program received signal SIGTRAP.*" "continue to PIC"
+gdb_breakpoint "gdb2029_marker"
+gdb_test "continue" "Breakpoint $decimal, $hex in gdb2029_marker \\(\\)" \
+       "continue to PIC"
 
 gdb_test "backtrace 10" \
-       "#0\[ \t\]*$hex in gdb2029.*\r\n#1\[ \t\]*$hex in main.*" \
+       "#0\[ \t\]*$hex in gdb2029_marker.*\r\n#1\[ \t\]*$hex in gdb2029.*\r\n#2\[ \t\]*$hex in main.*" \
+       "backtrace in PIC marker"
+
+gdb_test "finish" ".*$hex in gdb2029 .*" "finish from PIC"
+
+gdb_test "backtrace 10" \
+       "#0\[ \t\]*$hex in gdb2029 .*\r\n#1\[ \t\]*$hex in main.*" \
        "backtrace in PIC"
 
 gdb_test "info frame" \
        ".*Saved registers:.*r30 at.*r31 at.*pc at.*lr at.*" \
        "saved registers in PIC"
+
+# Testcase for scheduled prologue.
+
+gdb_breakpoint "optimized_1_marker"
+gdb_test "continue" "Breakpoint $decimal, $hex in optimized_1_marker \\(\\)" \
+       "continue to optimized"
+
+gdb_test "backtrace 10" \
+       "#0\[ \t\]*$hex in optimized_1_marker.*\r\n#1\[ \t\]*$hex in optimized_1.*\r\n#2\[ \t\]*$hex in main.*" \
+       "backtrace in optimized marker"
+
+gdb_test "finish" ".*$hex in optimized_1 .*" "finish from optimized"
+
+gdb_test "backtrace 10" \
+       "#0\[ \t\]*$hex in optimized_1 .*\r\n#1\[ \t\]*$hex in main.*" \
+       "backtrace in optimized"
+
+gdb_test "info frame" \
+       ".*Saved registers:.*r30 at.*r31 at.*pc at.*lr at.*" \
+       "saved registers in optimized"