python/19506 -- gdb.Breakpoint address location regression
[deliverable/binutils-gdb.git] / gdb / ppc64-tdep.c
index 60ef86a1c6f8a0a2233552e727c4974f7a3af264..b7357e3c43af98a85bedf977b5a9360957406282 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target-dependent code for ppc64 GDB, the GNU debugger.
 
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2016 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -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"
@@ -448,10 +449,13 @@ ppc64_standard_linkage4_target (struct frame_info *frame,
 
 
 /* Given that we've begun executing a call trampoline at PC, return
-   the entry point of the function the trampoline will go to.  */
+   the entry point of the function the trampoline will go to.
 
-CORE_ADDR
-ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+   When the execution direction is EXEC_REVERSE, scan backward to
+   check whether we are in the middle of a PLT stub.  */
+
+static CORE_ADDR
+ppc64_skip_trampoline_code_1 (struct frame_info *frame, CORE_ADDR pc)
 {
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
   unsigned int insns[MAX (MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1),
@@ -464,35 +468,80 @@ ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
                                    ARRAY_SIZE (ppc64_standard_linkage8))))
                     - 1];
   CORE_ADDR target;
+  int scan_limit, i;
+
+  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;
+}
+
+/* Wrapper of ppc64_skip_trampoline_code_1 checking also
+   ppc_elfv2_skip_entrypoint.  */
+
+CORE_ADDR
+ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
 
-  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;
+  pc = ppc64_skip_trampoline_code_1 (frame, pc);
+  if (pc != 0 && gdbarch_skip_entrypoint_p (gdbarch))
+    pc = gdbarch_skip_entrypoint (gdbarch, pc);
+  return pc;
 }
 
 /* Support for convert_from_func_ptr_addr (ARCH, ADDR, TARG) on PPC64
This page took 0.035402 seconds and 4 git commands to generate.