windows-nat.c: conflicting declaration of struct thread_info in C++ mode
[deliverable/binutils-gdb.git] / gdb / amd64-linux-tdep.c
index 97a2890ee20c570beb8872baccb5fea45c4717a8..b126366cafbcfbb8642c1ed318bc2907aba5232d 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for GNU/Linux x86-64.
 
-   Copyright (C) 2001-2014 Free Software Foundation, Inc.
+   Copyright (C) 2001-2015 Free Software Foundation, Inc.
    Contributed by Jiri Smid, SuSE Labs.
 
    This file is part of GDB.
 #include "gdbtypes.h"
 #include "reggroups.h"
 #include "regset.h"
+#include "parser-defs.h"
+#include "user-regs.h"
 #include "amd64-linux-tdep.h"
 #include "i386-linux-tdep.h"
 #include "linux-tdep.h"
-#include "i386-xstate.h"
+#include "x86-xstate.h"
 
 #include "amd64-tdep.h"
 #include "solib-svr4.h"
 #include "record-full.h"
 #include "linux-record.h"
 
-/* Supported register note sections.  */
-static struct core_regset_section amd64_linux_regset_sections[] =
-{
-  { ".reg", 27 * 8, "general-purpose" },
-  { ".reg2", 512, "floating-point" },
-  { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" },
-  { NULL, 0 }
-};
-
 /* Mapping between the general-purpose registers in `struct user'
    format and GDB's register cache layout.  */
 
@@ -1583,20 +1576,20 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
   /* Linux/x86-64.  */
   uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
 
-  switch (xcr0 & I386_XSTATE_ALL_MASK)
+  switch (xcr0 & X86_XSTATE_ALL_MASK)
     {
-    case I386_XSTATE_MPX_AVX512_MASK:
-    case I386_XSTATE_AVX512_MASK:
+    case X86_XSTATE_MPX_AVX512_MASK:
+    case X86_XSTATE_AVX512_MASK:
       if (gdbarch_ptr_bit (gdbarch) == 32)
        return tdesc_x32_avx512_linux;
       else
        return tdesc_amd64_avx512_linux;
-    case I386_XSTATE_MPX_MASK:
+    case X86_XSTATE_MPX_MASK:
       if (gdbarch_ptr_bit (gdbarch) == 32)
        return tdesc_x32_avx_linux;  /* No x32 MPX falling back to AVX.  */
       else
        return tdesc_amd64_mpx_linux;
-    case I386_XSTATE_AVX_MASK:
+    case X86_XSTATE_AVX_MASK:
       if (gdbarch_ptr_bit (gdbarch) == 32)
        return tdesc_x32_avx_linux;
       else
@@ -1609,6 +1602,189 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
     }
 }
 
+/* Similar to amd64_supply_fpregset, but use XSAVE extended state.  */
+
+static void
+amd64_linux_supply_xstateregset (const struct regset *regset,
+                                struct regcache *regcache, int regnum,
+                                const void *xstateregs, size_t len)
+{
+  amd64_supply_xsave (regcache, regnum, xstateregs);
+}
+
+/* Similar to amd64_collect_fpregset, but use XSAVE extended state.  */
+
+static void
+amd64_linux_collect_xstateregset (const struct regset *regset,
+                                 const struct regcache *regcache,
+                                 int regnum, void *xstateregs, size_t len)
+{
+  amd64_collect_xsave (regcache, regnum, xstateregs, 1);
+}
+
+static const struct regset amd64_linux_xstateregset =
+  {
+    NULL,
+    amd64_linux_supply_xstateregset,
+    amd64_linux_collect_xstateregset
+  };
+
+/* Iterate over core file register note sections.  */
+
+static void
+amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
+                                         iterate_over_regset_sections_cb *cb,
+                                         void *cb_data,
+                                         const struct regcache *regcache)
+{
+  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),
+      &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
+}
+
+/* The instruction sequences used in x86_64 machines for a
+   disabled is-enabled probe.  */
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_1[] = {
+  /* xor %rax, %rax */  0x48, 0x33, 0xc0,
+  /* nop            */  0x90,
+  /* nop            */  0x90
+};
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_2[] = {
+  /* xor %rax, %rax */  0x48, 0x33, 0xc0,
+  /* ret            */  0xc3,
+  /* nop            */  0x90
+};
+
+/* The instruction sequence used in x86_64 machines for enabling a
+   DTrace is-enabled probe.  */
+
+const gdb_byte amd64_dtrace_enable_probe_sequence[] = {
+  /* mov $0x1, %eax */ 0xb8, 0x01, 0x00, 0x00, 0x00
+};
+
+/* The instruction sequence used in x86_64 machines for disabling a
+   DTrace is-enabled probe.  */
+
+const gdb_byte amd64_dtrace_disable_probe_sequence[] = {
+  /* xor %rax, %rax; nop; nop */ 0x48, 0x33, 0xC0, 0x90, 0x90
+};
+
+/* Implementation of `gdbarch_dtrace_probe_is_enabled', as defined in
+   gdbarch.h.  */
+
+static int
+amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  gdb_byte buf[5];
+
+  /* This function returns 1 if the instructions at ADDR do _not_
+     follow any of the amd64_dtrace_disabled_probe_sequence_*
+     patterns.
+
+     Note that ADDR is offset 3 bytes from the beginning of these
+     sequences.  */
+  
+  read_code (addr - 3, buf, 5);
+  return (memcmp (buf, amd64_dtrace_disabled_probe_sequence_1, 5) != 0
+         && memcmp (buf, amd64_dtrace_disabled_probe_sequence_2, 5) != 0);
+}
+
+/* Implementation of `gdbarch_dtrace_enable_probe', as defined in
+   gdbarch.h.  */
+
+static void
+amd64_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  /* Note also that ADDR is offset 3 bytes from the beginning of
+     amd64_dtrace_enable_probe_sequence.  */
+
+  write_memory (addr - 3, amd64_dtrace_enable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_disable_probe', as defined in
+   gdbarch.h.  */
+
+static void
+amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  /* Note also that ADDR is offset 3 bytes from the beginning of
+     amd64_dtrace_disable_probe_sequence.  */
+
+  write_memory (addr - 3, amd64_dtrace_disable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_parse_probe_argument', as defined
+   in gdbarch.h.  */
+
+static void
+amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
+                                  struct parser_state *pstate,
+                                  int narg)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct frame_info *this_frame = get_selected_frame (NULL);
+  struct stoken str;
+
+  /* DTrace probe arguments can be found on the ABI-defined places for
+     regular arguments at the current PC.  The probe abstraction
+     currently supports up to 12 arguments for probes.  */
+
+  if (narg < 6)
+    {
+      static const int arg_reg_map[6] =
+       {
+         AMD64_RDI_REGNUM,  /* Arg 1.  */
+         AMD64_RSI_REGNUM,  /* Arg 2.  */
+         AMD64_RDX_REGNUM,  /* Arg 3.  */
+         AMD64_RCX_REGNUM,  /* Arg 4.  */
+         AMD64_R8_REGNUM,   /* Arg 5.  */
+         AMD64_R9_REGNUM    /* Arg 6.  */
+       };
+      int regno = arg_reg_map[narg];
+      const char *regname = user_reg_map_regnum_to_name (gdbarch, regno);
+
+      write_exp_elt_opcode (pstate, OP_REGISTER);
+      str.ptr = regname;
+      str.length = strlen (regname);
+      write_exp_string (pstate, str);
+      write_exp_elt_opcode (pstate, OP_REGISTER);
+    }
+  else
+    {
+      /* Additional arguments are passed on the stack.  */
+      CORE_ADDR sp;
+      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);
+
+      /* Register: SP.  */
+      write_exp_elt_opcode (pstate, OP_REGISTER);
+      str.ptr = regname;
+      str.length = strlen (regname);
+      write_exp_string (pstate, str);
+      write_exp_elt_opcode (pstate, OP_REGISTER);
+
+      write_exp_elt_opcode (pstate, BINOP_ADD);
+
+      /* Cast to long. */
+      write_exp_elt_opcode (pstate, UNOP_CAST);
+      write_exp_elt_type (pstate,
+                         lookup_pointer_type (builtin_type (gdbarch)->builtin_long));
+      write_exp_elt_opcode (pstate, UNOP_CAST);
+
+      write_exp_elt_opcode (pstate, UNOP_IND);
+    }
+}
+
 static void
 amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -1629,7 +1805,7 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->register_reggroup_p = amd64_linux_register_reggroup_p;
 
   /* Functions for 'catch syscall'.  */
-  set_xml_syscall_file_name (XML_SYSCALL_FILENAME_AMD64);
+  set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_AMD64);
   set_gdbarch_get_syscall_number (gdbarch,
                                   amd64_linux_get_syscall_number);
 
@@ -1643,8 +1819,9 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
   /* GNU/Linux uses the dynamic linker included in the GNU C Library.  */
   set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
 
-  /* Install supported register note sections.  */
-  set_gdbarch_core_regset_sections (gdbarch, amd64_linux_regset_sections);
+  /* Iterate over core file register note sections.  */
+  set_gdbarch_iterate_over_regset_sections
+    (gdbarch, amd64_linux_iterate_over_regset_sections);
 
   set_gdbarch_core_read_description (gdbarch,
                                     amd64_linux_core_read_description);
@@ -1872,6 +2049,12 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* GNU/Linux uses SVR4-style shared libraries.  */
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_lp64_fetch_link_map_offsets);
+
+  /* Register DTrace handlers.  */
+  set_gdbarch_dtrace_parse_probe_argument (gdbarch, amd64_dtrace_parse_probe_argument);
+  set_gdbarch_dtrace_probe_is_enabled (gdbarch, amd64_dtrace_probe_is_enabled);
+  set_gdbarch_dtrace_enable_probe (gdbarch, amd64_dtrace_enable_probe);
+  set_gdbarch_dtrace_disable_probe (gdbarch, amd64_dtrace_disable_probe);
 }
 
 static void
This page took 0.026953 seconds and 4 git commands to generate.