Skip-trampoline for PowerPC reverse-stepping.
authorWei-cheng Wang <cole945@gmail.com>
Sat, 17 Jan 2015 06:30:59 +0000 (14:30 +0800)
committerCole Wang <cole945@gmail.com>
Sat, 17 Jan 2015 11:48:22 +0000 (19:48 +0800)
gdb/ChangeLog
gdb/ppc-linux-tdep.c
gdb/ppc64-tdep.c

index 6866edb954dd04584a96150406497d397b40d6ca..d4008e9c49717ae1db526ff8fb6a8f747895dfd3 100644 (file)
@@ -1,3 +1,9 @@
+2015-01-17  Wei-cheng Wang  <cole945@gmail.com>
+
+       * ppc-linux-tdep.c (ppc_skip_trampoline_code):
+       Scan PLT stub backward for reverse debugging.
+       * ppc64-tdep.c (ppc64_skip_trampoline_code): Likewise.
+
 2015-01-17  Wei-cheng Wang  <cole945@gmail.com>
            Ulrich Weigand  <uweigand@de.ibm.com>
 
index dcfd3bb9f9746377499bf8edf03601ddbcca46f1..13bb479fe3a375b9d4ac830637fc4ae782579c20 100644 (file)
@@ -51,6 +51,7 @@
 #include "linux-tdep.h"
 #include "linux-record.h"
 #include "record-full.h"
+#include "infrun.h"
 
 #include "stap-probe.h"
 #include "ax.h"
@@ -314,31 +315,50 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR target = 0;
+  int scan_limit, i;
 
-  if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
-    {
-      /* Insn pattern is
-               lis   r11, xxxx
-               lwz   r11, xxxx(r11)
-        Branch target is in r11.  */
-
-      target = (ppc_insn_d_field (insnbuf[0]) << 16)
-       | ppc_insn_d_field (insnbuf[1]);
-      target = read_memory_unsigned_integer (target, 4, byte_order);
-    }
+  scan_limit = 1;
+  /* When reverse-debugging, scan backward to check whether we are
+     in the middle of trampoline code.  */
+  if (execution_direction == EXEC_REVERSE)
+    scan_limit = 4;    /* At more 4 instructions.  */
 
-  if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so, insnbuf))
+  for (i = 0; i < scan_limit; i++)
     {
-      /* Insn pattern is
-               lwz   r11, xxxx(r30)
-        Branch target is in r11.  */
+      if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
+       {
+         /* Insn pattern is
+            lis   r11, xxxx
+            lwz   r11, xxxx(r11)
+            Branch target is in r11.  */
+
+         target = (ppc_insn_d_field (insnbuf[0]) << 16)
+                  | ppc_insn_d_field (insnbuf[1]);
+         target = read_memory_unsigned_integer (target, 4, byte_order);
+       }
+      else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so,
+                                       insnbuf))
+       {
+         /* Insn pattern is
+            lwz   r11, xxxx(r30)
+            Branch target is in r11.  */
+
+         target = get_frame_register_unsigned (frame,
+                                               tdep->ppc_gp0_regnum + 30)
+                  + ppc_insn_d_field (insnbuf[0]);
+         target = read_memory_unsigned_integer (target, 4, byte_order);
+       }
+      else
+       {
+         /* Scan backward one more instructions if doesn't match.  */
+         pc -= 4;
+         continue;
+       }
 
-      target = get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 30)
-              + ppc_insn_d_field (insnbuf[0]);
-      target = read_memory_unsigned_integer (target, 4, byte_order);
+      return target;
     }
 
-  return target;
+  return 0;
 }
 
 /* Wrappers to handle Linux-only registers.  */
index 60ef86a1c6f8a0a2233552e727c4974f7a3af264..66d7b2362e1487326ff139a2fe6f0ae1da941ddc 100644 (file)
@@ -20,6 +20,7 @@
 #include "defs.h"
 #include "frame.h"
 #include "gdbcore.h"
+#include "infrun.h"
 #include "ppc-tdep.h"
 #include "ppc64-tdep.h"
 #include "elf-bfd.h"
@@ -464,35 +465,66 @@ ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
                                    ARRAY_SIZE (ppc64_standard_linkage8))))
                     - 1];
   CORE_ADDR target;
+  int scan_limit, i;
 
-  if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
-    pc = ppc64_standard_linkage4_target (frame, pc, insns);
-  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
-    pc = ppc64_standard_linkage3_target (frame, pc, insns);
-  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6, insns))
-    pc = ppc64_standard_linkage4_target (frame, pc, insns);
-  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5, insns)
-          && (insns[8] != 0 || insns[9] != 0))
-    pc = ppc64_standard_linkage3_target (frame, pc, insns);
-  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4, insns)
-          && (insns[9] != 0 || insns[10] != 0))
-    pc = ppc64_standard_linkage4_target (frame, pc, insns);
-  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3, insns)
-          && (insns[8] != 0 || insns[9] != 0))
-    pc = ppc64_standard_linkage3_target (frame, pc, insns);
-  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2, insns)
-          && (insns[10] != 0 || insns[11] != 0))
-    pc = ppc64_standard_linkage2_target (frame, pc, insns);
-  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage1, insns))
-    pc = ppc64_standard_linkage1_target (frame, pc, insns);
-  else
-    return 0;
-
-  /* The PLT descriptor will either point to the already resolved target
-     address, or else to a glink stub.  As the latter carry synthetic @plt
-     symbols, find_solib_trampoline_target should be able to resolve them.  */
-  target = find_solib_trampoline_target (frame, pc);
-  return target ? target : pc;
+  scan_limit = 1;
+  /* When reverse-debugging, scan backward to check whether we are
+     in the middle of trampoline code.  */
+  if (execution_direction == EXEC_REVERSE)
+    scan_limit = ARRAY_SIZE (insns) - 1;
+
+  for (i = 0; i < scan_limit; i++)
+    {
+      if (i < ARRAY_SIZE (ppc64_standard_linkage8) - 1
+         && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
+       pc = ppc64_standard_linkage4_target (frame, pc, insns);
+      else if (i < ARRAY_SIZE (ppc64_standard_linkage7) - 1
+              && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7,
+                                          insns))
+       pc = ppc64_standard_linkage3_target (frame, pc, insns);
+      else if (i < ARRAY_SIZE (ppc64_standard_linkage6) - 1
+              && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6,
+                                          insns))
+       pc = ppc64_standard_linkage4_target (frame, pc, insns);
+      else if (i < ARRAY_SIZE (ppc64_standard_linkage5) - 1
+              && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5,
+                                          insns)
+              && (insns[8] != 0 || insns[9] != 0))
+       pc = ppc64_standard_linkage3_target (frame, pc, insns);
+      else if (i < ARRAY_SIZE (ppc64_standard_linkage4) - 1
+              && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4,
+                                          insns)
+              && (insns[9] != 0 || insns[10] != 0))
+       pc = ppc64_standard_linkage4_target (frame, pc, insns);
+      else if (i < ARRAY_SIZE (ppc64_standard_linkage3) - 1
+              && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3,
+                                          insns)
+              && (insns[8] != 0 || insns[9] != 0))
+       pc = ppc64_standard_linkage3_target (frame, pc, insns);
+      else if (i < ARRAY_SIZE (ppc64_standard_linkage2) - 1
+              && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2,
+                                          insns)
+              && (insns[10] != 0 || insns[11] != 0))
+       pc = ppc64_standard_linkage2_target (frame, pc, insns);
+      else if (i < ARRAY_SIZE (ppc64_standard_linkage1) - 1
+              && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage1,
+                                          insns))
+       pc = ppc64_standard_linkage1_target (frame, pc, insns);
+      else
+       {
+         /* Scan backward one more instructions if doesn't match.  */
+         pc -= 4;
+         continue;
+       }
+
+      /* The PLT descriptor will either point to the already resolved target
+         address, or else to a glink stub.  As the latter carry synthetic @plt
+         symbols, find_solib_trampoline_target should be able to resolve them.  */
+      target = find_solib_trampoline_target (frame, pc);
+      return target ? target : pc;
+  }
+
+  return 0;
 }
 
 /* Support for convert_from_func_ptr_addr (ARCH, ADDR, TARG) on PPC64