[PATCH V3 6/9] Support for DTrace USDT probes in x86_64 targets.

"Jose E. Marchesi" <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
This patch adds the target-specific code in order to support the
calculation of DTrace probes arguments in x86_64 targets, and also the
enabling and disabling of probes.  This is done by implementing the
`dtrace_*' gdbarch handlers.

gdb/ChangeLog:

  2014-10-28  Jose E. Marchesi  <[email protected]>

	* amd64-linux-tdep.c: Include "parser-defs.h" and "user-regs.h".
	(amd64_dtrace_parse_probe_argument): New function.
	(amd64_dtrace_probe_is_enabled): Likewise.
	(amd64_dtrace_enable_probe): Likewise.
	(amd64_dtrace_disable_probe): Likewise.
	(amd64_linux_init_abi): Register the
	`gdbarch_dtrace_probe_argument', `gdbarch_dtrace_enable_probe',
	`gdbarch_dtrace_disable_probe' and
	`gdbarch_dtrace_probe_is_enabled' hooks.
	(amd64_dtrace_disabled_probe_sequence_1): New constant.
	(amd64_dtrace_disabled_probe_sequence_2): Likewise.
	(amd64_dtrace_enable_probe_sequence): Likewise.
	(amd64_dtrace_disable_probe_sequence): Likewise.
---
 gdb/ChangeLog          |   16 ++++++
 gdb/amd64-linux-tdep.c |  148 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+)

diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index edbb1b3..9fe68b9 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -28,6 +28,8 @@
 #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"
@@ -1643,6 +1645,146 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
       &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)
 {
@@ -1907,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
-- 
1.7.10.4
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.