gdb: change single_displaced_buffer_manager into multiple_displaced_buffer_manager
[deliverable/binutils-gdb.git] / gdb / amd64-linux-tdep.c
index 85efbefd1289bbe1770e5e55c185df0af69e15aa..4cb33d5b5d2a55cfa51ae98951ae97088c74631e 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for GNU/Linux x86-64.
 
-   Copyright (C) 2001-2017 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
    Contributed by Jiri Smid, SuSE Labs.
 
    This file is part of GDB.
@@ -20,7 +20,9 @@
 
 #include "defs.h"
 #include "arch-utils.h"
+#include "displaced-stepping.h"
 #include "frame.h"
+#include "gdbarch.h"
 #include "gdbcore.h"
 #include "regcache.h"
 #include "osabi.h"
 #include "amd64-linux-tdep.h"
 #include "i386-linux-tdep.h"
 #include "linux-tdep.h"
-#include "x86-xstate.h"
+#include "gdbsupport/x86-xstate.h"
+#include "inferior.h"
 
 #include "amd64-tdep.h"
 #include "solib-svr4.h"
 #include "xml-syscall.h"
 #include "glibc-tdep.h"
-
-#include "features/i386/amd64-linux.c"
-#include "features/i386/amd64-avx-linux.c"
-#include "features/i386/amd64-mpx-linux.c"
-#include "features/i386/amd64-avx-mpx-linux.c"
-#include "features/i386/amd64-avx-avx512-linux.c"
-#include "features/i386/amd64-avx-mpx-avx512-pku-linux.c"
-
-#include "features/i386/x32-linux.c"
-#include "features/i386/x32-avx-linux.c"
-#include "features/i386/x32-avx-avx512-linux.c"
+#include "arch/amd64.h"
+#include "target-descriptions.h"
 
 /* The syscall's XML filename for i386.  */
 #define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml"
@@ -231,9 +225,9 @@ amd64_linux_sigcontext_addr (struct frame_info *this_frame)
 
 static LONGEST
 amd64_linux_get_syscall_number (struct gdbarch *gdbarch,
-                                ptid_t ptid)
+                               thread_info *thread)
 {
-  struct regcache *regcache = get_thread_regcache (ptid);
+  struct regcache *regcache = get_thread_regcache (thread);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* The content of a register.  */
   gdb_byte buf[8];
@@ -243,7 +237,7 @@ amd64_linux_get_syscall_number (struct gdbarch *gdbarch,
   /* Getting the system call number from the register.
      When dealing with x86_64 architecture, this information
      is stored at %rax register.  */
-  regcache_cooked_read (regcache, AMD64_LINUX_ORIG_RAX_REGNUM, buf);
+  regcache->cooked_read (AMD64_LINUX_ORIG_RAX_REGNUM, buf);
 
   ret = extract_signed_integer (buf, 8, byte_order);
 
@@ -372,6 +366,9 @@ amd64_all_but_ip_registers_record (struct regcache *regcache)
 static enum gdb_syscall
 amd64_canonicalize_syscall (enum amd64_syscall syscall_number)
 {
+  DIAGNOSTIC_PUSH
+  DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
+
   switch (syscall_number) {
   case amd64_sys_read:
   case amd64_x32_sys_read:
@@ -1439,6 +1436,8 @@ amd64_canonicalize_syscall (enum amd64_syscall syscall_number)
   default:
     return gdb_sys_no_syscall;
   }
+
+  DIAGNOSTIC_POP
 }
 
 /* Parse the arguments of current system call instruction and record
@@ -1578,42 +1577,30 @@ amd64_linux_record_signal (struct gdbarch *gdbarch,
 const target_desc *
 amd64_linux_read_description (uint64_t xcr0_features_bit, bool is_x32)
 {
-  switch (xcr0_features_bit)
+  static target_desc *amd64_linux_tdescs \
+    [2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/] = {};
+  static target_desc *x32_linux_tdescs[2/*AVX*/][2/*AVX512*/] = {};
+
+  target_desc **tdesc;
+
+  if (is_x32)
     {
-    case X86_XSTATE_AVX_MPX_AVX512_PKU_MASK:
-      if (is_x32)
-       /* No MPX, PKU on x32, fallback to AVX-AVX512.  */
-       return tdesc_x32_avx_avx512_linux;
-      else
-       return tdesc_amd64_avx_mpx_avx512_pku_linux;
-    case X86_XSTATE_AVX_AVX512_MASK:
-      if (is_x32)
-       return tdesc_x32_avx_avx512_linux;
-      else
-       return tdesc_amd64_avx_avx512_linux;
-    case X86_XSTATE_MPX_MASK:
-      if (is_x32)
-       /* No MPX on x32, fallback to AVX.  */
-       return tdesc_x32_avx_linux;
-      else
-       return tdesc_amd64_mpx_linux;
-    case X86_XSTATE_AVX_MPX_MASK:
-      if (is_x32)
-       /* No MPX on x32, fallback to AVX.  */
-       return tdesc_x32_avx_linux;
-      else
-       return tdesc_amd64_avx_mpx_linux;
-    case X86_XSTATE_AVX_MASK:
-      if (is_x32)
-       return tdesc_x32_avx_linux;
-      else
-       return tdesc_amd64_avx_linux;
-    default:
-      if (is_x32)
-       return tdesc_x32_linux;
-      else
-       return tdesc_amd64_linux;
+      tdesc = &x32_linux_tdescs[(xcr0_features_bit & X86_XSTATE_AVX) ? 1 : 0 ]
+       [(xcr0_features_bit & X86_XSTATE_AVX512) ? 1 : 0];
     }
+  else
+    {
+      tdesc = &amd64_linux_tdescs[(xcr0_features_bit & X86_XSTATE_AVX) ? 1 : 0]
+       [(xcr0_features_bit & X86_XSTATE_MPX) ? 1 : 0]
+       [(xcr0_features_bit & X86_XSTATE_AVX512) ? 1 : 0]
+       [(xcr0_features_bit & X86_XSTATE_PKRU) ? 1 : 0];
+    }
+
+  if (*tdesc == NULL)
+    *tdesc = amd64_create_target_description (xcr0_features_bit, is_x32,
+                                             true, true);
+
+  return *tdesc;
 }
 
 /* Get Linux/x86 target description from core dump.  */
@@ -1667,9 +1654,9 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", 27 * 8, &i386_gregset, NULL, cb_data);
-  cb (".reg2", 512, &amd64_fpregset, NULL, cb_data);
-  cb (".reg-xstate",  X86_XSTATE_SIZE (tdep->xcr0),
+  cb (".reg", 27 * 8, 27 * 8, &i386_gregset, NULL, cb_data);
+  cb (".reg2", 512, 512, &amd64_fpregset, NULL, cb_data);
+  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
       &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
 }
 
@@ -1751,7 +1738,7 @@ amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
 
 static void
 amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
-                                  struct parser_state *pstate,
+                                  struct expr_builder *builder,
                                   int narg)
 {
   struct stoken str;
@@ -1774,11 +1761,11 @@ amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
       int regno = arg_reg_map[narg];
       const char *regname = user_reg_map_regnum_to_name (gdbarch, regno);
 
-      write_exp_elt_opcode (pstate, OP_REGISTER);
+      write_exp_elt_opcode (builder, OP_REGISTER);
       str.ptr = regname;
       str.length = strlen (regname);
-      write_exp_string (pstate, str);
-      write_exp_elt_opcode (pstate, OP_REGISTER);
+      write_exp_string (builder, str);
+      write_exp_elt_opcode (builder, OP_REGISTER);
     }
   else
     {
@@ -1786,28 +1773,81 @@ amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
       const char *regname = user_reg_map_regnum_to_name (gdbarch, AMD64_RSP_REGNUM);
 
       /* Displacement.  */
-      write_exp_elt_opcode (pstate, OP_LONG);
-      write_exp_elt_type (pstate, builtin_type (gdbarch)->builtin_long);
-      write_exp_elt_longcst (pstate, narg - 6);
-      write_exp_elt_opcode (pstate, OP_LONG);
+      write_exp_elt_opcode (builder, OP_LONG);
+      write_exp_elt_type (builder, builtin_type (gdbarch)->builtin_long);
+      write_exp_elt_longcst (builder, narg - 6);
+      write_exp_elt_opcode (builder, OP_LONG);
 
       /* Register: SP.  */
-      write_exp_elt_opcode (pstate, OP_REGISTER);
+      write_exp_elt_opcode (builder, OP_REGISTER);
       str.ptr = regname;
       str.length = strlen (regname);
-      write_exp_string (pstate, str);
-      write_exp_elt_opcode (pstate, OP_REGISTER);
+      write_exp_string (builder, str);
+      write_exp_elt_opcode (builder, OP_REGISTER);
 
-      write_exp_elt_opcode (pstate, BINOP_ADD);
+      write_exp_elt_opcode (builder, BINOP_ADD);
 
       /* Cast to long. */
-      write_exp_elt_opcode (pstate, UNOP_CAST);
-      write_exp_elt_type (pstate,
+      write_exp_elt_opcode (builder, UNOP_CAST);
+      write_exp_elt_type (builder,
                          lookup_pointer_type (builtin_type (gdbarch)->builtin_long));
-      write_exp_elt_opcode (pstate, UNOP_CAST);
+      write_exp_elt_opcode (builder, UNOP_CAST);
+
+      write_exp_elt_opcode (builder, UNOP_IND);
+    }
+}
+
+struct amd64_linux_per_inferior
+{
+  amd64_linux_per_inferior (gdb::array_view<CORE_ADDR> disp_step_buffer_addrs)
+    : disp_step_buf_mgr (disp_step_buffer_addrs)
+  {}
+
+  multiple_displaced_buffer_manager disp_step_buf_mgr;
+};
+
+static const inferior_key<amd64_linux_per_inferior>
+  amd64_linux_per_inferior_data;
 
-      write_exp_elt_opcode (pstate, UNOP_IND);
+/* Get the per-inferior AMD64/Linux data for INF.  */
+
+static amd64_linux_per_inferior *
+get_amd64_linux_per_inferior (inferior *inf, gdbarch *arch)
+{
+  amd64_linux_per_inferior *per_inf = amd64_linux_per_inferior_data.get (inf);
+
+  if (per_inf == nullptr)
+    {
+      /* Figure out where the displaced step buffer is.  */
+      CORE_ADDR disp_step_buffer_addr = linux_displaced_step_location (arch);
+
+      per_inf = amd64_linux_per_inferior_data.emplace (inf, disp_step_buffer_addr);
     }
+
+  return per_inf;
+}
+
+/* Implementation of the gdbarch_displaced_step_prepare method. */
+
+static displaced_step_prepare_status
+amd64_linux_displaced_step_prepare (gdbarch *arch, thread_info *thread)
+{
+  amd64_linux_per_inferior *per_inferior
+    = get_amd64_linux_per_inferior (thread->inf, arch);
+
+  return per_inferior->disp_step_buf_mgr.prepare (thread);
+}
+
+/* Implementation of the gdbarch_displaced_step_finish method. */
+
+static displaced_step_finish_status
+amd64_linux_displaced_step_finish (gdbarch *arch, thread_info *thread,
+                                  gdb_signal sig)
+{
+  amd64_linux_per_inferior *per_inferior
+    = get_amd64_linux_per_inferior (thread->inf, arch);
+
+  return per_inferior->disp_step_buf_mgr.finish (arch, thread, sig);
 }
 
 static void
@@ -1855,8 +1895,8 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_displaced_step_copy_insn (gdbarch,
                                         amd64_displaced_step_copy_insn);
   set_gdbarch_displaced_step_fixup (gdbarch, amd64_displaced_step_fixup);
-  set_gdbarch_displaced_step_location (gdbarch,
-                                       linux_displaced_step_location);
+  set_gdbarch_displaced_step_prepare (gdbarch, amd64_linux_displaced_step_prepare);
+  set_gdbarch_displaced_step_finish (gdbarch, amd64_linux_displaced_step_finish);
 
   set_gdbarch_process_record (gdbarch, i386_process_record);
   set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal);
@@ -2287,28 +2327,13 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 }
-\f
-
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern void _initialize_amd64_linux_tdep (void);
 
+void _initialize_amd64_linux_tdep ();
 void
-_initialize_amd64_linux_tdep (void)
+_initialize_amd64_linux_tdep ()
 {
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
                          GDB_OSABI_LINUX, amd64_linux_init_abi);
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x64_32,
                          GDB_OSABI_LINUX, amd64_x32_linux_init_abi);
-
-  /* Initialize the Linux target description.  */
-  initialize_tdesc_amd64_linux ();
-  initialize_tdesc_amd64_avx_linux ();
-  initialize_tdesc_amd64_mpx_linux ();
-  initialize_tdesc_amd64_avx_mpx_linux ();
-  initialize_tdesc_amd64_avx_avx512_linux ();
-  initialize_tdesc_amd64_avx_mpx_avx512_pku_linux ();
-
-  initialize_tdesc_x32_linux ();
-  initialize_tdesc_x32_avx_linux ();
-  initialize_tdesc_x32_avx_avx512_linux ();
 }
This page took 0.028893 seconds and 4 git commands to generate.