Add native target for FreeBSD/mips.
[deliverable/binutils-gdb.git] / gdb / ppc64-tdep.c
index 8732182db3049b5f0a4b1e915b2d5a84756ff049..563d2537c2b617aa0a429eddedc5d520f5649bb3 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target-dependent code for ppc64 GDB, the GNU debugger.
 
-   Copyright (C) 1986-2013 Free Software Foundation, Inc.
+   Copyright (C) 1986-2017 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"
    | (((spr) & 0x3e0) << 6)                     \
    | (((xo) & 0x3ff) << 1))
 
-/* If DESC is the address of a 64-bit PowerPC FreeBSD function
-   descriptor, return the descriptor's entry point.  */
+/* If PLT is the address of a 64-bit PowerPC PLT entry,
+   return the function's entry point.  */
 
 static CORE_ADDR
-ppc64_desc_entry_point (struct gdbarch *gdbarch, CORE_ADDR desc)
+ppc64_plt_entry_point (struct gdbarch *gdbarch, CORE_ADDR plt)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  /* The first word of the descriptor is the entry point.  */
-  return (CORE_ADDR) read_memory_unsigned_integer (desc, 8, byte_order);
+  /* The first word of the PLT entry is the function entry point.  */
+  return (CORE_ADDR) read_memory_unsigned_integer (plt, 8, byte_order);
 }
 
 /* Patterns for the standard linkage functions.  These are built by
    build_plt_stub in bfd/elf64-ppc.c.  */
 
-/* Old PLT call stub.  */
+/* Old ELFv1 PLT call stub.  */
 
 static struct ppc_insn_pattern ppc64_standard_linkage1[] =
   {
@@ -96,7 +97,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage1[] =
     { 0, 0, 0 }
   };
 
-/* Current PLT call stub to access PLT entries more than +/- 32k from r2.
+/* ELFv1 PLT call stub to access PLT entries more than +/- 32k from r2.
    Also supports older stub with different placement of std 2,40(1),
    a stub that omits the std 2,40(1), and both versions of power7
    thread safety read barriers.  Note that there are actually two more
@@ -144,7 +145,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage2[] =
     { 0, 0, 0 }
   };
 
-/* Current PLT call stub to access PLT entries within +/- 32k of r2.  */
+/* ELFv1 PLT call stub to access PLT entries within +/- 32k of r2.  */
 
 static struct ppc_insn_pattern ppc64_standard_linkage3[] =
   {
@@ -181,6 +182,151 @@ static struct ppc_insn_pattern ppc64_standard_linkage3[] =
     { 0, 0, 0 }
   };
 
+/* ELFv1 PLT call stub to access PLT entries more than +/- 32k from r2.
+   A more modern variant of ppc64_standard_linkage2 differing in
+   register usage.  */
+
+static struct ppc_insn_pattern ppc64_standard_linkage4[] =
+  {
+    /* std r2, 40(r1) <optional> */
+    { -1, insn_ds (62, 2, 1, 40, 0), 1 },
+
+    /* addis r11, r2, <any> */
+    { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 },
+
+    /* ld r12, <any>(r11) */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 11, 0, 0), 0 },
+
+    /* addi r11, r11, <any> <optional> */
+    { insn_d (-1, -1, -1, 0), insn_d (14, 11, 11, 0), 1 },
+
+    /* mtctr r12 */
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
+
+    /* xor r2, r12, r12 <optional> */
+    { -1, 0x7d826278, 1 },
+
+    /* add r11, r11, r2 <optional> */
+    { -1, 0x7d6b1214, 1 },
+
+    /* ld r2, <any>(r11) */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 11, 0, 0), 0 },
+
+    /* ld r11, <any>(r11) <optional> */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 11, 0, 0), 1 },
+
+    /* bctr <optional> */
+    { -1, 0x4e800420, 1 },
+
+    /* cmpldi r2, 0 <optional> */
+    { -1, 0x28220000, 1 },
+
+    { 0, 0, 0 }
+  };
+
+/* ELFv1 PLT call stub to access PLT entries within +/- 32k of r2.
+   A more modern variant of ppc64_standard_linkage3 differing in
+   register usage.  */
+
+static struct ppc_insn_pattern ppc64_standard_linkage5[] =
+  {
+    /* std r2, 40(r1) <optional> */
+    { -1, insn_ds (62, 2, 1, 40, 0), 1 },
+
+    /* ld r12, <any>(r2) */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 2, 0, 0), 0 },
+
+    /* addi r2, r2, <any> <optional> */
+    { insn_d (-1, -1, -1, 0), insn_d (14, 2, 2, 0), 1 },
+
+    /* mtctr r12 */
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
+
+    /* xor r11, r12, r12 <optional> */
+    { -1, 0x7d8b6278, 1 },
+
+    /* add r2, r2, r11 <optional> */
+    { -1, 0x7c425a14, 1 },
+
+    /* ld r11, <any>(r2) <optional> */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 2, 0, 0), 1 },
+
+    /* ld r2, <any>(r2) */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 2, 0, 0), 0 },
+
+    /* bctr <optional> */
+    { -1, 0x4e800420, 1 },
+
+    /* cmpldi r2, 0 <optional> */
+    { -1, 0x28220000, 1 },
+
+    { 0, 0, 0 }
+  };
+
+/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2.  */
+
+static struct ppc_insn_pattern ppc64_standard_linkage6[] =
+  {
+    /* std r2, 24(r1) <optional> */
+    { -1, insn_ds (62, 2, 1, 24, 0), 1 },
+
+    /* addis r11, r2, <any> */
+    { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 },
+
+    /* ld r12, <any>(r11) */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 11, 0, 0), 0 },
+
+    /* mtctr r12 */
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
+
+    /* bctr */
+    { -1, 0x4e800420, 0 },
+
+    { 0, 0, 0 }
+  };
+
+/* ELFv2 PLT call stub to access PLT entries within +/- 32k of r2.  */
+
+static struct ppc_insn_pattern ppc64_standard_linkage7[] =
+  {
+    /* std r2, 24(r1) <optional> */
+    { -1, insn_ds (62, 2, 1, 24, 0), 1 },
+
+    /* ld r12, <any>(r2) */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 2, 0, 0), 0 },
+
+    /* mtctr r12 */
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
+
+    /* bctr */
+    { -1, 0x4e800420, 0 },
+
+    { 0, 0, 0 }
+  };
+
+/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2,
+   supporting fusion.  */
+
+static struct ppc_insn_pattern ppc64_standard_linkage8[] =
+  {
+    /* std r2, 24(r1) <optional> */
+    { -1, insn_ds (62, 2, 1, 24, 0), 1 },
+
+    /* addis r12, r2, <any> */
+    { insn_d (-1, -1, -1, 0), insn_d (15, 12, 2, 0), 0 },
+
+    /* ld r12, <any>(r12) */
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 12, 0, 0), 0 },
+
+    /* mtctr r12 */
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
+
+    /* bctr */
+    { -1, 0x4e800420, 0 },
+
+    { 0, 0, 0 }
+  };
+
 /* When the dynamic linker is doing lazy symbol resolution, the first
    call to a function in another object will go like this:
 
@@ -243,16 +389,14 @@ ppc64_standard_linkage1_target (struct frame_info *frame,
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  /* The address of the function descriptor this linkage function
-     references.  */
-  CORE_ADDR desc
+  /* The address of the PLT entry this linkage function references.  */
+  CORE_ADDR plt
     = ((CORE_ADDR) get_frame_register_unsigned (frame,
                                                tdep->ppc_gp0_regnum + 2)
        + (ppc_insn_d_field (insn[0]) << 16)
        + ppc_insn_ds_field (insn[2]));
 
-  /* The first word of the descriptor is the entry point.  Return that.  */
-  return ppc64_desc_entry_point (gdbarch, desc);
+  return ppc64_plt_entry_point (gdbarch, plt);
 }
 
 static CORE_ADDR
@@ -262,16 +406,14 @@ ppc64_standard_linkage2_target (struct frame_info *frame,
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  /* The address of the function descriptor this linkage function
-     references.  */
-  CORE_ADDR desc
+  /* The address of the PLT entry this linkage function references.  */
+  CORE_ADDR plt
     = ((CORE_ADDR) get_frame_register_unsigned (frame,
                                                tdep->ppc_gp0_regnum + 2)
        + (ppc_insn_d_field (insn[1]) << 16)
        + ppc_insn_ds_field (insn[3]));
 
-  /* The first word of the descriptor is the entry point.  Return that.  */
-  return ppc64_desc_entry_point (gdbarch, desc);
+  return ppc64_plt_entry_point (gdbarch, plt);
 }
 
 static CORE_ADDR
@@ -281,46 +423,125 @@ ppc64_standard_linkage3_target (struct frame_info *frame,
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  /* The address of the function descriptor this linkage function
-     references.  */
-  CORE_ADDR desc
+  /* The address of the PLT entry this linkage function references.  */
+  CORE_ADDR plt
     = ((CORE_ADDR) get_frame_register_unsigned (frame,
                                                tdep->ppc_gp0_regnum + 2)
        + ppc_insn_ds_field (insn[1]));
 
-  /* The first word of the descriptor is the entry point.  Return that.  */
-  return ppc64_desc_entry_point (gdbarch, desc);
+  return ppc64_plt_entry_point (gdbarch, plt);
+}
+
+static CORE_ADDR
+ppc64_standard_linkage4_target (struct frame_info *frame,
+                               CORE_ADDR pc, unsigned int *insn)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  CORE_ADDR plt
+    = ((CORE_ADDR) get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 2)
+       + (ppc_insn_d_field (insn[1]) << 16)
+       + ppc_insn_ds_field (insn[2]));
+
+  return ppc64_plt_entry_point (gdbarch, plt);
 }
 
 
 /* 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 (ARRAY_SIZE (ppc64_standard_linkage1),
-                              ARRAY_SIZE (ppc64_standard_linkage2)),
-                         ARRAY_SIZE (ppc64_standard_linkage3)) - 1];
+  unsigned int insns[MAX (MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1),
+                                   ARRAY_SIZE (ppc64_standard_linkage2)),
+                              MAX (ARRAY_SIZE (ppc64_standard_linkage3),
+                                   ARRAY_SIZE (ppc64_standard_linkage4))),
+                         MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage5),
+                                   ARRAY_SIZE (ppc64_standard_linkage6)),
+                              MAX (ARRAY_SIZE (ppc64_standard_linkage7),
+                                   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_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
@@ -383,7 +604,8 @@ ppc64_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
       gdb_byte buf[8];
       int res;
 
-      res = bfd_get_section_contents (s->bfd, s->the_bfd_section,
+      res = bfd_get_section_contents (s->the_bfd_section->owner,
+                                     s->the_bfd_section,
                                      &buf, addr - s->addr, 8);
       if (res != 0)
        return extract_unsigned_integer (buf, 8, byte_order)
This page took 0.034387 seconds and 4 git commands to generate.