[V3,5/9] New probe type: DTrace USDT probes.

Message ID 1414504218-31204-6-git-send-email-jose.marchesi@oracle.com
State Superseded
Headers

Commit Message

Jose E. Marchesi Oct. 28, 2014, 1:50 p.m. UTC
  This patch adds a new type of probe to GDB: the DTrace USDT probes.  The new
type is added by providing functions implementing all the entries of the
`probe_ops' structure defined in `probe.h'.  The implementation is
self-contained and does not depend on DTrace source code in any way.

gdb/ChangeLog:

  2014-10-28  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* breakpoint.c (BREAK_ARGS_HELP): help string updated to mention
	the -probe-dtrace new vpossible value for PROBE_MODIFIER.
	* configure.ac (CONFIG_OBS): dtrace-probe.o added if BFD can
	handle ELF files.
	* Makefile.in (SFILES): dtrace-probe.c added.
	* configure: Regenerate.
	* dtrace-probe.c: New file.
	(SHT_SUNW_dof): New constant.
	(dtrace_probe_type): New enum.
	(dtrace_probe_arg): New struct.
	(dtrace_probe_arg_s): New typedef.
	(struct dtrace_probe_enabler): New struct.
	(dtrace_probe_enabler_s): New typedef.
	(dtrace_probe): New struct.
	(dtrace_probe_is_linespec): New function.
	(dtrace_dof_sect_type): New enum.
	(dtrace_dof_dofh_ident): Likewise.
	(dtrace_dof_encoding): Likewise.
	(DTRACE_DOF_ENCODE_LSB): Likewise.
	(DTRACE_DOF_ENCODE_MSB): Likewise.
	(dtrace_dof_hdr): New struct.
	(dtrace_dof_sect): Likewise.
	(dtrace_dof_provider): Likewise.
	(dtrace_dof_probe): Likewise.
	(DOF_UINT): New macro.
	(DTRACE_DOF_PTR): Likewise.
	(DTRACE_DOF_SECT): Likewise.
	(dtrace_process_dof_probe): New function.
	(dtrace_process_dof): Likewise.
	(dtrace_build_arg_exprs): Likewise.
	(dtrace_get_arg): Likewise.
	(dtrace_get_probes): Likewise.
	(dtrace_get_probe_argument_count): Likewise.
	(dtrace_can_evaluate_probe_arguments): Likewise.
	(dtrace_evaluate_probe_argument): Likewise.
	(dtrace_compile_to_ax): Likewise.
	(dtrace_probe_destroy): Likewise.
	(dtrace_gen_info_probes_table_header): Likewise.
	(dtrace_gen_info_probes_table_values): Likewise.
	(dtrace_probe_is_enabled): Likewise.
	(dtrace_probe_ops): New variable.
	(info_probes_dtrace_command): New function.
	(_initialize_dtrace_probe): Likewise.
	(dtrace_type_name): Likewise.
---
 gdb/ChangeLog      |   47 +++
 gdb/Makefile.in    |    3 +-
 gdb/breakpoint.c   |    3 +-
 gdb/configure      |    2 +-
 gdb/configure.ac   |    2 +-
 gdb/dtrace-probe.c |  909 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 962 insertions(+), 4 deletions(-)
 create mode 100644 gdb/dtrace-probe.c
  

Comments

Sergio Durigan Junior Oct. 31, 2014, 8:03 p.m. UTC | #1
On Tuesday, October 28 2014, Jose E. Marchesi wrote:

> This patch adds a new type of probe to GDB: the DTrace USDT probes.  The new
> type is added by providing functions implementing all the entries of the
> `probe_ops' structure defined in `probe.h'.  The implementation is
> self-contained and does not depend on DTrace source code in any way.

Thanks!  I skimmed through the patch and did not see anything wrong with
it.  It seems to be in a much better shape than the first version, and
I'm happy with it.  I just want to take some more time to look deeper
into the details, but so far, so good.

> gdb/ChangeLog:
>
>   2014-10-28  Jose E. Marchesi  <jose.marchesi@oracle.com>
>
> 	* breakpoint.c (BREAK_ARGS_HELP): help string updated to mention
> 	the -probe-dtrace new vpossible value for PROBE_MODIFIER.
> 	* configure.ac (CONFIG_OBS): dtrace-probe.o added if BFD can
> 	handle ELF files.
> 	* Makefile.in (SFILES): dtrace-probe.c added.
> 	* configure: Regenerate.
> 	* dtrace-probe.c: New file.
> 	(SHT_SUNW_dof): New constant.
> 	(dtrace_probe_type): New enum.
> 	(dtrace_probe_arg): New struct.
> 	(dtrace_probe_arg_s): New typedef.
> 	(struct dtrace_probe_enabler): New struct.
> 	(dtrace_probe_enabler_s): New typedef.
> 	(dtrace_probe): New struct.
> 	(dtrace_probe_is_linespec): New function.
> 	(dtrace_dof_sect_type): New enum.
> 	(dtrace_dof_dofh_ident): Likewise.
> 	(dtrace_dof_encoding): Likewise.
> 	(DTRACE_DOF_ENCODE_LSB): Likewise.
> 	(DTRACE_DOF_ENCODE_MSB): Likewise.
> 	(dtrace_dof_hdr): New struct.
> 	(dtrace_dof_sect): Likewise.
> 	(dtrace_dof_provider): Likewise.
> 	(dtrace_dof_probe): Likewise.
> 	(DOF_UINT): New macro.
> 	(DTRACE_DOF_PTR): Likewise.
> 	(DTRACE_DOF_SECT): Likewise.
> 	(dtrace_process_dof_probe): New function.
> 	(dtrace_process_dof): Likewise.
> 	(dtrace_build_arg_exprs): Likewise.
> 	(dtrace_get_arg): Likewise.
> 	(dtrace_get_probes): Likewise.
> 	(dtrace_get_probe_argument_count): Likewise.
> 	(dtrace_can_evaluate_probe_arguments): Likewise.
> 	(dtrace_evaluate_probe_argument): Likewise.
> 	(dtrace_compile_to_ax): Likewise.
> 	(dtrace_probe_destroy): Likewise.
> 	(dtrace_gen_info_probes_table_header): Likewise.
> 	(dtrace_gen_info_probes_table_values): Likewise.
> 	(dtrace_probe_is_enabled): Likewise.
> 	(dtrace_probe_ops): New variable.
> 	(info_probes_dtrace_command): New function.
> 	(_initialize_dtrace_probe): Likewise.
> 	(dtrace_type_name): Likewise.
> ---
>  gdb/ChangeLog      |   47 +++
>  gdb/Makefile.in    |    3 +-
>  gdb/breakpoint.c   |    3 +-
>  gdb/configure      |    2 +-
>  gdb/configure.ac   |    2 +-
>  gdb/dtrace-probe.c |  909 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 962 insertions(+), 4 deletions(-)
>  create mode 100644 gdb/dtrace-probe.c
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 1da8af6..a237a1f 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -800,7 +800,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
>  	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
>  	d-exp.y d-lang.c d-valprint.c \
>  	cp-name-parser.y \
> -	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
> +	dbxread.c demangle.c dictionary.c disasm.c doublest.c \
> +	dtrace-probe.c dummy-frame.c \
>  	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
>  	dwarf2-frame-tailcall.c \
>  	elfread.c environ.c eval.c event-loop.c event-top.c \
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index cab6c56..ebaa9ce 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -15998,7 +15998,8 @@ all_tracepoints (void)
>  command" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]\n\
>  PROBE_MODIFIER shall be present if the command is to be placed in a\n\
>  probe point.  Accepted values are `-probe' (for a generic, automatically\n\
> -guessed probe type) or `-probe-stap' (for a SystemTap probe).\n\
> +guessed probe type), `-probe-stap' (for a SystemTap probe) or \n\
> +`-probe-dtrace' (for a DTrace probe).\n\
>  LOCATION may be a line number, function name, or \"*\" and an address.\n\
>  If a line number is specified, break at start of code for that line.\n\
>  If a function is specified, break at start of code for that function.\n\
> diff --git a/gdb/configure b/gdb/configure
> index 1d6d88b..a1660bc 100755
> --- a/gdb/configure
> +++ b/gdb/configure
> @@ -13241,7 +13241,7 @@ $as_echo "$gdb_cv_var_elf" >&6; }
>    LDFLAGS=$OLD_LDFLAGS
>    LIBS=$OLD_LIBS
>  if test $gdb_cv_var_elf = yes; then
> -  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o"
> +  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o"
>  
>  $as_echo "#define HAVE_ELF 1" >>confdefs.h
>  
> diff --git a/gdb/configure.ac b/gdb/configure.ac
> index 2d73669..4ac5f7b 100644
> --- a/gdb/configure.ac
> +++ b/gdb/configure.ac
> @@ -2063,7 +2063,7 @@ AC_SUBST(WIN32LIBS)
>  GDB_AC_CHECK_BFD([for ELF support in BFD], gdb_cv_var_elf,
>                   [bfd_get_elf_phdr_upper_bound (NULL)], elf-bfd.h)
>  if test $gdb_cv_var_elf = yes; then
> -  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o"
> +  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o"
>    AC_DEFINE(HAVE_ELF, 1,
>  	    [Define if ELF support should be included.])
>    # -ldl is provided by bfd/Makfile.am (LIBDL) <PLUGINS>.
> diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
> new file mode 100644
> index 0000000..f4bfc70
> --- /dev/null
> +++ b/gdb/dtrace-probe.c
> @@ -0,0 +1,909 @@
> +/* DTrace probe support for GDB.
> +
> +   Copyright (C) 2014 Free Software Foundation, Inc.
> +
> +   Contributed by Oracle, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "defs.h"
> +#include "probe.h"
> +#include "vec.h"
> +#include "elf-bfd.h"
> +#include "gdbtypes.h"
> +#include "obstack.h"
> +#include "objfiles.h"
> +#include "complaints.h"
> +#include "value.h"
> +#include "ax.h"
> +#include "ax-gdb.h"
> +#include "language.h"
> +#include "parser-defs.h"
> +#include "inferior.h"
> +
> +/* The type of the ELF sections where we will find the DOF programs
> +   with information about probes.  */
> +
> +#ifndef SHT_SUNW_dof
> +# define SHT_SUNW_dof	0x6ffffff4
> +#endif
> +
> +/* Forward declaration.  */
> +
> +static const struct probe_ops dtrace_probe_ops;
> +
> +/* The following structure represents a single argument for the
> +   probe.  */
> +
> +struct dtrace_probe_arg
> +{
> +  /* The type of the probe argument.  */
> +  struct type *type;
> +
> +  /* A string describing the type.  */
> +  char *type_str;
> +
> +  /* The argument converted to an internal GDB expression.  */
> +  struct expression *expr;
> +};
> +
> +typedef struct dtrace_probe_arg dtrace_probe_arg_s;
> +DEF_VEC_O (dtrace_probe_arg_s);
> +
> +/* The following structure represents an enabler for a probe.  */
> +
> +struct dtrace_probe_enabler
> +{
> +  /* Program counter where the is-enabled probe is installed.  The
> +     contents (nops, whatever...) stored at this address are
> +     architecture dependent.  */
> +  CORE_ADDR address;
> +};
> +
> +typedef struct dtrace_probe_enabler dtrace_probe_enabler_s;
> +DEF_VEC_O (dtrace_probe_enabler_s);
> +
> +/* The following structure represents a dtrace probe.  */
> +
> +struct dtrace_probe
> +{
> +  /* Generic information about the probe.  This must be the first
> +     element of this struct, in order to maintain binary compatibility
> +     with the `struct probe' and be able to fully abstract it.  */
> +  struct probe p;
> +
> +  /* A probe can have zero or more arguments.  */
> +  int probe_argc;
> +  VEC (dtrace_probe_arg_s) *args;
> +
> +  /* A probe can have zero or more "enablers" associated with it.  */
> +  VEC (dtrace_probe_enabler_s) *enablers;
> +
> +  /* Whether the expressions for the arguments have been built.  */
> +  unsigned int args_expr_built : 1;
> +};
> +
> +/* Implementation of the probe_is_linespec method.  */
> +
> +static int
> +dtrace_probe_is_linespec (const char **linespecp)
> +{
> +  static const char *const keywords[] = { "-pdtrace", "-probe-dtrace", NULL };
> +
> +  return probe_is_linespec_by_keyword (linespecp, keywords);
> +}
> +
> +/* DOF programs can contain an arbitrary number of sections of 26
> +   different types.  In order to support DTrace USDT probes we only
> +   need to handle a subset of these section types, fortunately.  These
> +   section types are defined in the following enumeration.
> +
> +   See linux/dtrace/dof_defines.h for a complete list of section types
> +   along with their values.  */
> +
> +enum dtrace_dof_sect_type
> +{
> +  /* Null section.  */
> +  DTRACE_DOF_SECT_TYPE_NONE     = 0,
> +  /* A dof_ecbdesc_t. */
> +  DTRACE_DOF_SECT_TYPE_ECBDESC  = 3,
> +  /* A string table.  */
> +  DTRACE_DOF_SECT_TYPE_STRTAB   = 8,
> +  /* A dof_provider_t  */
> +  DTRACE_DOF_SECT_TYPE_PROVIDER = 15,
> +  /* Array of dof_probe_t  */
> +  DTRACE_DOF_SECT_TYPE_PROBES   = 16,
> +  /* An array of probe arg mappings.  */
> +  DTRACE_DOF_SECT_TYPE_PRARGS   = 17,
> +  /* An array of probe arg offsets.  */
> +  DTRACE_DOF_SECT_TYPE_PROFFS   = 18,
> +  /* An array of probe is-enabled offsets.  */
> +  DTRACE_DOF_SECT_TYPE_PRENOFFS = 26
> +};
> +
> +/* The following collection of data structures map the structure of
> +   DOF entities.  Again, we only cover the subset of DOF used to
> +   implement USDT probes.
> +
> +   See linux/dtrace/dof.h header for a complete list of data
> +   structures.  */
> +
> +/* Offsets to index the dofh_ident[] array defined below.  */
> +
> +enum dtrace_dof_ident
> +{
> +  /* First byte of the magic number.  */
> +  DTRACE_DOF_ID_MAG0     = 0,
> +  /* Second byte of the magic number.  */
> +  DTRACE_DOF_ID_MAG1     = 1,
> +  /* Third byte of the magic number.  */
> +  DTRACE_DOF_ID_MAG2     = 2,
> +  /* Fourth byte of the magic number.  */
> +  DTRACE_DOF_ID_MAG3     = 3,
> +  /* An enum_dof_encoding value.  */
> +  DTRACE_DOF_ID_ENCODING = 5
> +};
> +
> +/* Possible values for dofh_ident[DOF_ID_ENCODING].  */
> +
> +enum dtrace_dof_encoding
> +{
> +  /* The DOF program is little-endian.  */
> +  DTRACE_DOF_ENCODE_LSB = 1,
> +  /* The DOF program is big-endian.  */
> +  DTRACE_DOF_ENCODE_MSB = 2
> +};
> +
> +/* A DOF header, which describes the contents of a DOF program: number
> +   of sections, size, etc.  */
> +
> +struct dtrace_dof_hdr
> +{
> +  /* Identification bytes (see above). */
> +  uint8_t dofh_ident[16];
> +  /* File attribute flags (if any). */
> +  uint32_t dofh_flags;   
> +  /* Size of file header in bytes. */
> +  uint32_t dofh_hdrsize; 
> +  /* Size of section header in bytes. */
> +  uint32_t dofh_secsize; 
> +  /* Number of section headers. */
> +  uint32_t dofh_secnum;  
> +  /* File offset of section headers. */
> +  uint64_t dofh_secoff;  
> +  /* File size of loadable portion. */
> +  uint64_t dofh_loadsz;  
> +  /* File size of entire DOF file. */
> +  uint64_t dofh_filesz;  
> +  /* Reserved for future use. */
> +  uint64_t dofh_pad;     
> +};
> +
> +/* A DOF section, whose contents depend on its type.  The several
> +   supported section types are described in the enum
> +   dtrace_dof_sect_type above.  */
> +
> +struct dtrace_dof_sect
> +{
> +  /* Section type (see the define above). */
> +  uint32_t dofs_type;
> +  /* Section data memory alignment. */
> +  uint32_t dofs_align; 
> +  /* Section flags (if any). */
> +  uint32_t dofs_flags; 
> +  /* Size of section entry (if table). */
> +  uint32_t dofs_entsize;
> +  /* DOF + offset points to the section data. */
> +  uint64_t dofs_offset;
> +  /* Size of section data in bytes.  */
> +  uint64_t dofs_size;  
> +};
> +
> +/* A DOF provider, which is the provider of a probe.  */
> +
> +struct dtrace_dof_provider
> +{
> +  /* Link to a DTRACE_DOF_SECT_TYPE_STRTAB section. */
> +  uint32_t dofpv_strtab; 
> +  /* Link to a DTRACE_DOF_SECT_TYPE_PROBES section. */
> +  uint32_t dofpv_probes; 
> +  /* Link to a DTRACE_DOF_SECT_TYPE_PRARGS section. */
> +  uint32_t dofpv_prargs; 
> +  /* Link to a DTRACE_DOF_SECT_TYPE_PROFFS section. */
> +  uint32_t dofpv_proffs; 
> +  /* Provider name string. */
> +  uint32_t dofpv_name;   
> +  /* Provider attributes. */
> +  uint32_t dofpv_provattr;
> +  /* Module attributes. */
> +  uint32_t dofpv_modattr; 
> +  /* Function attributes. */
> +  uint32_t dofpv_funcattr;
> +  /* Name attributes. */
> +  uint32_t dofpv_nameattr;
> +  /* Args attributes. */
> +  uint32_t dofpv_argsattr;
> +  /* Link to a DTRACE_DOF_SECT_PRENOFFS section. */
> +  uint32_t dofpv_prenoffs;
> +};
> +
> +/* A set of DOF probes and is-enabled probes sharing a base address
> +   and several attributes.  The particular locations and attributes of
> +   each probe are maintained in arrays in several other DOF sections.
> +   See the comment in dtrace_process_dof_probe for details on how
> +   these attributes are stored.  */
> +
> +struct dtrace_dof_probe
> +{
> +  /* Probe base address or offset. */
> +  uint64_t dofpr_addr;   
> +  /* Probe function string. */
> +  uint32_t dofpr_func;   
> +  /* Probe name string. */
> +  uint32_t dofpr_name;   
> +  /* Native argument type strings. */
> +  uint32_t dofpr_nargv;  
> +  /* Translated argument type strings. */
> +  uint32_t dofpr_xargv;  
> +  /* Index of first argument mapping. */
> +  uint32_t dofpr_argidx; 
> +  /* Index of first offset entry. */
> +  uint32_t dofpr_offidx; 
> +  /* Native argument count. */
> +  uint8_t  dofpr_nargc;  
> +  /* Translated argument count. */
> +  uint8_t  dofpr_xargc;  
> +  /* Number of offset entries for probe. */
> +  uint16_t dofpr_noffs;  
> +  /* Index of first is-enabled offset. */
> +  uint32_t dofpr_enoffidx;
> +  /* Number of is-enabled offsets. */
> +  uint16_t dofpr_nenoffs;
> +  /* Reserved for future use. */
> +  uint16_t dofpr_pad1;   
> +  /* Reserved for future use. */
> +  uint32_t dofpr_pad2;   
> +};
> +
> +/* DOF supports two different encodings: MSB (big-endian) and LSB
> +   (little-endian).  The encoding is itself encoded in the DOF header.
> +   The following function returns an unsigned value in the host
> +   endianness.  */
> +
> +#define DOF_UINT(dof, field)						\
> +  extract_unsigned_integer ((gdb_byte *) &(field),			\
> +			    sizeof ((field)),				\
> +			    (((dof)->dofh_ident[DTRACE_DOF_ID_ENCODING] \
> +			      == DTRACE_DOF_ENCODE_MSB)			\
> +			     ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE))
> +
> +/* The following macro applies a given byte offset to a DOF (a pointer
> +   to a dtrace_dof_hdr structure) and returns the resulting
> +   address.  */
> +
> +#define DTRACE_DOF_PTR(dof, offset) (&((char *) (dof))[(offset)])
> +
> +/* The following macro returns a pointer to the beginning of a given
> +   section in a DOF object.  The section is referred to by its index
> +   in the sections array.  */
> +
> +#define DTRACE_DOF_SECT(dof, idx)					\
> +  ((struct dtrace_dof_sect *)						\
> +   DTRACE_DOF_PTR ((dof),						\
> +		   DOF_UINT ((dof), (dof)->dofh_secoff)			\
> +		   + ((idx) * DOF_UINT ((dof), (dof)->dofh_secsize))))
> +
> +/* Helper function to examine the probe described by the given PROBE
> +   and PROVIDER data structures and add it to the PROBESP vector.
> +   STRTAB, OFFTAB, EOFFTAB and ARGTAB are pointers to tables in the
> +   DOF program containing the attributes for the probe.  */
> +
> +static void
> +dtrace_process_dof_probe (struct objfile *objfile,
> +			  struct gdbarch *gdbarch, VEC (probe_p) **probesp,
> +			  struct dtrace_dof_hdr *dof,
> +			  struct dtrace_dof_probe *probe,
> +			  struct dtrace_dof_provider *provider,
> +			  char *strtab, char *offtab, char *eofftab,
> +			  char *argtab, uint64_t strtab_size)
> +{
> +  int i, j, num_probes, num_enablers;
> +  struct cleanup *cleanup;
> +  VEC (dtrace_probe_enabler_s) *enablers;
> +  char *p;
> +
> +  /* Each probe section can define zero or more probes of two
> +     different types:
> +
> +     - probe->dofpr_noffs regular probes whose program counters are
> +       stored in 32bit words starting at probe->dofpr_addr +
> +       offtab[probe->dofpr_offidx].
> +
> +     - probe->dofpr_nenoffs is-enabled probes whose program counters
> +       are stored in 32bit words starting at probe->dofpr_addr +
> +       eofftab[probe->dofpr_enoffidx].
> +
> +     However is-enabled probes are not probes per-se, but an
> +     optimization hack that is implemented in the kernel in a very
> +     similar way than normal probes.  This is how we support
> +     is-enabled probes on GDB:
> +
> +     - Our probes are always DTrace regular probes.
> +
> +     - Our probes can be associated with zero or more "enablers".  The
> +       list of enablers is built from the is-enabled probes defined in
> +       the Probe section.
> +
> +     - Probes having a non-empty list of enablers can be enabled or
> +       disabled using the `enable probe' and `disable probe' commands
> +       respectively.  The `Enabled' column in the output of `info
> +       probes' will read `yes' if the enablers are activated, `no'
> +       otherwise.
> +
> +     - Probes having an empty list of enablers are always enabled.
> +       The `Enabled' column in the output of `info probes' will
> +       read `always'.
> +
> +     It follows that if there are DTrace is-enabled probes defined for
> +     some provider/name but no DTrace regular probes defined then the
> +     GDB user wont be able to enable/disable these conditionals.  */
> +
> +  num_probes = DOF_UINT (dof, probe->dofpr_noffs);
> +  if (num_probes == 0)
> +    return;
> +
> +  /* Build the list of enablers for the probes defined in this Probe
> +     DOF section.  */
> +  enablers = NULL;
> +  cleanup
> +    = make_cleanup (VEC_cleanup (dtrace_probe_enabler_s), &enablers);
> +  num_enablers = DOF_UINT (dof, probe->dofpr_nenoffs);
> +  for (i = 0; i < num_enablers; i++)
> +    {
> +      struct dtrace_probe_enabler enabler;
> +      uint32_t enabler_offset
> +	= ((uint32_t *) eofftab)[DOF_UINT (dof, probe->dofpr_enoffidx) + i];
> +
> +      enabler.address = DOF_UINT (dof, probe->dofpr_addr)
> +	+ DOF_UINT (dof, enabler_offset);
> +      VEC_safe_push (dtrace_probe_enabler_s, enablers, &enabler);
> +    }
> +
> +  for (i = 0; i < num_probes; i++)
> +    {
> +      uint32_t probe_offset
> +	= ((uint32_t *) offtab)[DOF_UINT (dof, probe->dofpr_offidx) + i];
> +      struct dtrace_probe *ret
> +	= obstack_alloc (&objfile->per_bfd->storage_obstack, sizeof (*ret));
> +
> +      ret->p.pops = &dtrace_probe_ops;
> +      ret->p.arch = gdbarch;
> +      ret->args_expr_built = 0;
> +
> +      /* Set the provider and the name of the probe.  */
> +      ret->p.provider
> +	= xstrdup (strtab + DOF_UINT (dof, provider->dofpv_name));
> +      ret->p.name = xstrdup (strtab + DOF_UINT (dof, probe->dofpr_name));
> +
> +      /* The probe address.  */
> +      ret->p.address
> +	= DOF_UINT (dof, probe->dofpr_addr) + DOF_UINT (dof, probe_offset);
> +
> +      /* Number of arguments in the probe.  */
> +      ret->probe_argc = DOF_UINT (dof, probe->dofpr_nargc);
> +
> +      /* Store argument type descriptions.  A description of the type
> +         of the argument is in the (J+1)th null-terminated string
> +         starting at 'strtab' + 'probe->dofpr_nargv'.  */
> +      ret->args = NULL;
> +      p = strtab + DOF_UINT (dof, probe->dofpr_nargv);
> +      for (j = 0; j < ret->probe_argc; j++)
> +	{
> +	  struct dtrace_probe_arg arg;
> +	  struct expression *expr;
> +
> +	  arg.type_str = xstrdup (p);
> +
> +	  /* Use strtab_size as a sentinel.  */
> +	  while (*p++ != '\0' && p - strtab < strtab_size);
> +
> +	  /* Try to parse a type expression from the type string.  If
> +	     this does not work then we set the type to `long
> +	     int'.  */
> +          arg.type = builtin_type (gdbarch)->builtin_long;
> +	  expr = parse_expression (arg.type_str);
> +	  if (expr->elts[0].opcode == OP_TYPE)
> +	    arg.type = expr->elts[1].type;
> +
> +	  VEC_safe_push (dtrace_probe_arg_s, ret->args, &arg);
> +	}
> +
> +      /* Add the vector of enablers to this probe, if any.  */
> +      ret->enablers = VEC_copy (dtrace_probe_enabler_s, enablers);
> +
> +      /* Successfully created probe.  */
> +      VEC_safe_push (probe_p, *probesp, (struct probe *) ret);
> +    }
> +
> +  do_cleanups (cleanup);
> +}
> +
> +/* Helper function to collect the probes described in the DOF program
> +   whose header is pointed by DOF and add them to the PROBESP vector.
> +   SECT is the ELF section containing the DOF program and OBJFILE is
> +   its containing object file.  */
> +
> +static void
> +dtrace_process_dof (asection *sect, struct objfile *objfile,
> +		    VEC (probe_p) **probesp, struct dtrace_dof_hdr *dof)
> +{
> +  bfd *abfd = objfile->obfd;
> +  int size = bfd_get_arch_size (abfd) / 8;
> +  struct gdbarch *gdbarch = get_objfile_arch (objfile);
> +  struct dtrace_dof_sect *section;
> +  int i;
> +
> +  /* The first step is to check for the DOF magic number.  If no valid
> +     DOF data is found in the section then a complaint is issued to
> +     the user and the section skipped.  */
> +  if (dof->dofh_ident[DTRACE_DOF_ID_MAG0] != 0x7F
> +      || dof->dofh_ident[DTRACE_DOF_ID_MAG1] != 'D'
> +      || dof->dofh_ident[DTRACE_DOF_ID_MAG2] != 'O'
> +      || dof->dofh_ident[DTRACE_DOF_ID_MAG3] != 'F')
> +    goto invalid_dof_data;
> +
> +  /* Make sure the encoding mark is either DTRACE_DOF_ENCODE_LSB or
> +     DTRACE_DOF_ENCODE_MSB.  */
> +  if (dof->dofh_ident[DTRACE_DOF_ID_ENCODING] != DTRACE_DOF_ENCODE_LSB
> +      && dof->dofh_ident[DTRACE_DOF_ID_ENCODING] != DTRACE_DOF_ENCODE_MSB)
> +    goto invalid_dof_data;
> +
> +  /* Make sure this DOF is not an enabling DOF, i.e. there are no ECB
> +     Description sections.  */
> +  section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
> +						       DOF_UINT (dof, dof->dofh_secoff));
> +  for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
> +    if (section->dofs_type == DTRACE_DOF_SECT_TYPE_ECBDESC)
> +      return;
> +
> +  /* Iterate over any section of type Provider and extract the probe
> +     information from them.  If there are no "provider" sections on
> +     the DOF then we just return.  */
> +  section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
> +						       DOF_UINT (dof, dof->dofh_secoff));
> +  for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
> +    if (DOF_UINT (dof, section->dofs_type) == DTRACE_DOF_SECT_TYPE_PROVIDER)
> +      {
> +	struct dtrace_dof_provider *provider = (struct dtrace_dof_provider *)
> +	  DTRACE_DOF_PTR (dof, DOF_UINT (dof, section->dofs_offset));
> +	struct dtrace_dof_sect *strtab_s
> +	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_strtab));
> +	struct dtrace_dof_sect *probes_s
> +	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_probes));
> +	struct dtrace_dof_sect *args_s
> +	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prargs));
> +	struct dtrace_dof_sect *offsets_s
> +	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_proffs));
> +	struct dtrace_dof_sect *eoffsets_s
> +	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prenoffs));
> +	char *strtab  = DTRACE_DOF_PTR (dof, DOF_UINT (dof, strtab_s->dofs_offset));
> +	char *offtab  = DTRACE_DOF_PTR (dof, DOF_UINT (dof, offsets_s->dofs_offset));
> +	char *eofftab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, eoffsets_s->dofs_offset));
> +	char *argtab  = DTRACE_DOF_PTR (dof, DOF_UINT (dof, args_s->dofs_offset));
> +	unsigned int entsize = DOF_UINT (dof, probes_s->dofs_entsize);
> +	int num_probes;
> +
> +	/* Very, unlikely, but could crash gdb if not handled
> +	   properly.  */
> +	if (entsize == 0)
> +	  goto invalid_dof_data;
> +
> +	num_probes = DOF_UINT (dof, probes_s->dofs_size) / entsize;
> +
> +	for (i = 0; i < num_probes; i++)
> +	  {
> +	    struct dtrace_dof_probe *probe = (struct dtrace_dof_probe *)
> +	      DTRACE_DOF_PTR (dof, DOF_UINT (dof, probes_s->dofs_offset)
> +			      + (i * DOF_UINT (dof, probes_s->dofs_entsize)));
> +
> +	    dtrace_process_dof_probe (objfile,
> +				      gdbarch, probesp,
> +				      dof, probe,
> +				      provider, strtab, offtab, eofftab, argtab,
> +				      DOF_UINT (dof, strtab_s->dofs_size));
> +	  }
> +      }
> +
> +  return;
> +	  
> + invalid_dof_data:
> +  complaint (&symfile_complaints,
> +	     _("skipping section '%s' which does not contain valid DOF data."),
> +	     sect->name);
> +}
> +
> +/* Helper function to build the GDB internal expressiosn that, once
> +   evaluated, will calculate the values of the arguments of a given
> +   PROBE.  */
> +
> +static void
> +dtrace_build_arg_exprs (struct dtrace_probe *probe,
> +			struct gdbarch *gdbarch)
> +{
> +  struct parser_state pstate;
> +  struct dtrace_probe_arg *arg;
> +  int i;
> +
> +  probe->args_expr_built = 1;
> +
> +  /* Iterate over the arguments in the probe and build the
> +     corresponding GDB internal expression that will generate the
> +     value of the argument when executed at the PC of the probe.  */
> +  for (i = 0; i < probe->probe_argc; i++)
> +    {
> +      struct cleanup *back_to;
> +
> +      arg = VEC_index (dtrace_probe_arg_s, probe->args, i);
> +
> +      /* Initialize the expression buffer in the parser state.  The
> +	 language does not matter, since we are using our own
> +	 parser.  */
> +      initialize_expout (&pstate, 10, current_language, gdbarch);
> +      back_to = make_cleanup (free_current_contents, &pstate.expout);
> +
> +      /* The argument value, which is ABI dependent and casted to
> +	 `long int'.  */
> +      gdbarch_dtrace_parse_probe_argument (gdbarch, &pstate, i);
> +
> +      discard_cleanups (back_to);
> +
> +      /* Casting to the expected type, but only if the type was
> +	 recognized at probe load time.  Otherwise the argument will
> +	 be evaluated as the long integer passed to the probe.  */
> +      if (arg->type != NULL)
> +	{
> +	  write_exp_elt_opcode (&pstate, UNOP_CAST);
> +	  write_exp_elt_type   (&pstate, arg->type);
> +	  write_exp_elt_opcode (&pstate, UNOP_CAST);
> +	}     
> +
> +      reallocate_expout (&pstate);
> +      arg->expr = pstate.expout;
> +      prefixify_expression (arg->expr);
> +    }
> +}
> +
> +/* Helper function to return the Nth argument of a given PROBE.  */
> +
> +static struct dtrace_probe_arg *
> +dtrace_get_arg (struct dtrace_probe *probe, unsigned n,
> +		struct gdbarch *gdbarch)
> +{
> +  if (!probe->args_expr_built)
> +    dtrace_build_arg_exprs (probe, gdbarch);
> +
> +  return VEC_index (dtrace_probe_arg_s, probe->args, n);
> +}
> +
> +/* Implementation of the get_probes method.  */
> +
> +static void
> +dtrace_get_probes (VEC (probe_p) **probesp, struct objfile *objfile)
> +{
> +  bfd *abfd = objfile->obfd;
> +  asection *sect = NULL;
> +
> +  /* Do nothing in case this is a .debug file, instead of the objfile
> +     itself.  */
> +  if (objfile->separate_debug_objfile_backlink != NULL)
> +    return;
> +
> +  /* Iterate over the sections in OBJFILE looking for DTrace
> +     information.  */
> +  for (sect = abfd->sections; sect != NULL; sect = sect->next)
> +    {
> +      if (elf_section_data (sect)->this_hdr.sh_type == SHT_SUNW_dof)
> +	{
> +	  struct dtrace_dof_hdr *dof;
> +
> +	  /* Read the contents of the DOF section and then process it to
> +	     extract the information of any probe defined into it.  */
> +	  if (!bfd_malloc_and_get_section (abfd, sect, (bfd_byte **) &dof))
> +	    complaint (&symfile_complaints,
> +		       _("could not obtain the contents of"
> +			 "section '%s' in objfile `%s'."),
> +		       sect->name, abfd->filename);
> +      
> +	  dtrace_process_dof (sect, objfile, probesp, dof);
> +	  xfree (dof);
> +	}
> +    }
> +}
> +
> +/* Helper function to determine whether a given probe is "enabled" or
> +   "disabled".  A disabled probe is a probe in which one or more
> +   enablers are disabled.  */
> +
> +static int
> +dtrace_probe_is_enabled (struct dtrace_probe *probe)
> +{
> +  int i;
> +  struct gdbarch *gdbarch = probe->p.arch;
> +  struct dtrace_probe_enabler *enabler;
> +
> +  for (i = 0;
> +       VEC_iterate (dtrace_probe_enabler_s, probe->enablers, i, enabler);
> +       i++)
> +    if (!gdbarch_dtrace_probe_is_enabled (gdbarch, enabler->address))
> +      return 0;
> +
> +  return 1;
> +}
> +
> +/* Implementation of the get_probe_address method.  */
> +
> +static CORE_ADDR
> +dtrace_get_probe_address (struct probe *probe, struct objfile *objfile)
> +{
> +  gdb_assert (probe->pops == &dtrace_probe_ops);
> +  return probe->address + ANOFFSET (objfile->section_offsets,
> +				    SECT_OFF_DATA (objfile));
> +}
> +
> +/* Implementation of the get_probe_argument_count method.  */
> +
> +static unsigned
> +dtrace_get_probe_argument_count (struct probe *probe_generic,
> +				 struct frame_info *frame)
> +{
> +  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
> +
> +  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> +  return dtrace_probe->probe_argc;
> +}
> +
> +/* Implementation of the can_evaluate_probe_arguments method.  */
> +
> +static int
> +dtrace_can_evaluate_probe_arguments (struct probe *probe_generic)
> +{
> +  struct gdbarch *gdbarch = probe_generic->arch;
> +
> +  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +  return gdbarch_dtrace_parse_probe_argument_p (gdbarch);
> +}
> +
> +/* Implementation of the evaluate_probe_argument method.  */
> +
> +static struct value *
> +dtrace_evaluate_probe_argument (struct probe *probe_generic, unsigned n,
> +				struct frame_info *frame)
> +{
> +  struct gdbarch *gdbarch = probe_generic->arch;
> +  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
> +  struct dtrace_probe_arg *arg;
> +  int pos = 0;
> +
> +  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> +  arg = dtrace_get_arg (dtrace_probe, n, gdbarch);
> +  return evaluate_subexp_standard (arg->type, arg->expr, &pos, EVAL_NORMAL);
> +}
> +
> +/* Implementation of the compile_to_ax method.  */
> +
> +static void
> +dtrace_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr,
> +		      struct axs_value *value, unsigned n)
> +{
> +  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
> +  struct dtrace_probe_arg *arg;
> +  union exp_element *pc;
> +
> +  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> +  arg = dtrace_get_arg (dtrace_probe, n, expr->gdbarch);
> +
> +  pc = arg->expr->elts;
> +  gen_expr (arg->expr, &pc, expr, value);
> +
> +  require_rvalue (expr, value);
> +  value->type = arg->type;
> +}
> +
> +/* Implementation of the probe_destroy method.  */
> +
> +static void
> +dtrace_probe_destroy (struct probe *probe_generic)
> +{
> +  struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
> +  struct dtrace_probe_arg *arg;
> +  int i;
> +
> +  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> +  for (i = 0; VEC_iterate (dtrace_probe_arg_s, probe->args, i, arg); i++)
> +    {
> +      xfree (arg->type_str);
> +      xfree (arg->expr);
> +    }
> +
> +  VEC_free (dtrace_probe_enabler_s, probe->enablers);
> +  VEC_free (dtrace_probe_arg_s, probe->args);
> +}
> +
> +/* Implementation of the type_name method.  */
> +
> +static const char *
> +dtrace_type_name (struct probe *probe_generic)
> +{
> +  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +  return "dtrace";
> +}
> +
> +/* Implementation of the gen_info_probes_table_header method.  */
> +
> +static void
> +dtrace_gen_info_probes_table_header (VEC (info_probe_column_s) **heads)
> +{
> +  info_probe_column_s dtrace_probe_column;
> +
> +  dtrace_probe_column.field_name = "enabled";
> +  dtrace_probe_column.print_name = _("Enabled");
> +
> +  VEC_safe_push (info_probe_column_s, *heads, &dtrace_probe_column);
> +}
> +
> +/* Implementation of the gen_info_probes_table_values method.  */
> +
> +static void
> +dtrace_gen_info_probes_table_values (struct probe *probe_generic,
> +				     VEC (const_char_ptr) **ret)
> +{
> +  struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
> +  const char *val = NULL;
> +
> +  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
> +
> +  if (VEC_empty (dtrace_probe_enabler_s, probe->enablers))
> +    val = "always";
> +  else if (!gdbarch_dtrace_probe_is_enabled_p (probe_generic->arch))
> +    val = "unknown";
> +  else if (dtrace_probe_is_enabled (probe))
> +    val = "yes";
> +  else
> +    val = "no";
> +
> +  VEC_safe_push (const_char_ptr, *ret, val);
> +}
> +
> +/* Implementation of the enable_probe method.  */
> +
> +static void
> +dtrace_enable_probe (struct probe *probe)
> +{
> +  struct gdbarch *gdbarch = probe->arch;
> +  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
> +  struct dtrace_probe_enabler *enabler;
> +  int i;
> +
> +  gdb_assert (probe->pops == &dtrace_probe_ops);
> +
> +  /* Enabling a dtrace probe implies patching the text section of the
> +     running process, so make sure the inferior is indeed running.  */
> +  if (ptid_equal (inferior_ptid, null_ptid))
> +    error (_("No inferior running"));
> +
> +  /* Fast path.  */
> +  if (dtrace_probe_is_enabled (dtrace_probe))
> +    return;
> +
> +  /* Iterate over all defined enabler in the given probe and enable
> +     them all using the corresponding gdbarch hook.  */
> +
> +  for (i = 0;
> +       VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
> +       i++)
> +    if (gdbarch_dtrace_enable_probe_p (gdbarch))
> +      gdbarch_dtrace_enable_probe (gdbarch, enabler->address);
> +}
> +
> +
> +/* Implementation of the disable_probe method.  */
> +
> +static void
> +dtrace_disable_probe (struct probe *probe)
> +{
> +  struct gdbarch *gdbarch = probe->arch;
> +  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
> +  struct dtrace_probe_enabler *enabler;
> +  int i;
> +
> +  gdb_assert (probe->pops == &dtrace_probe_ops);
> +
> +  /* Disabling a dtrace probe implies patching the text section of the
> +     running process, so make sure the inferior is indeed running.  */
> +  if (ptid_equal (inferior_ptid, null_ptid))
> +    error (_("No inferior running"));
> +
> +  /* Fast path.  */
> +  if (!dtrace_probe_is_enabled (dtrace_probe))
> +    return;
> +
> +  /* Are we trying to disable a probe that does not have any enabler
> +     associated?  */
> +  if (VEC_empty (dtrace_probe_enabler_s, dtrace_probe->enablers))
> +    error (_("Probe %s:%s cannot be disabled."), probe->provider, probe->name);
> +
> +  /* Iterate over all defined enabler in the given probe and disable
> +     them all using the corresponding gdbarch hook.  */
> +
> +  for (i = 0;
> +       VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
> +       i++)
> +    {
> +      if (gdbarch_dtrace_disable_probe_p (gdbarch))
> +	gdbarch_dtrace_disable_probe (gdbarch, enabler->address);
> +    }
> +}
> +
> +/* DTrace probe_ops.  */
> +
> +static const struct probe_ops dtrace_probe_ops =
> +{
> +  dtrace_probe_is_linespec,
> +  dtrace_get_probes,
> +  dtrace_get_probe_address,
> +  dtrace_get_probe_argument_count,
> +  dtrace_can_evaluate_probe_arguments,
> +  dtrace_evaluate_probe_argument,
> +  dtrace_compile_to_ax,
> +  NULL, /* set_semaphore  */
> +  NULL, /* clear_semaphore  */
> +  dtrace_probe_destroy,
> +  dtrace_type_name,
> +  dtrace_gen_info_probes_table_header,
> +  dtrace_gen_info_probes_table_values,
> +  dtrace_enable_probe,
> +  dtrace_disable_probe
> +};
> +
> +/* Implementation of the `info probes dtrace' command.  */
> +
> +static void
> +info_probes_dtrace_command (char *arg, int from_tty)
> +{
> +  info_probes_for_ops (arg, from_tty, &dtrace_probe_ops);
> +}
> +
> +void _initialize_dtrace_probe (void);
> +
> +void
> +_initialize_dtrace_probe (void)
> +{
> +  VEC_safe_push (probe_ops_cp, all_probe_ops, &dtrace_probe_ops);
> +
> +  add_cmd ("dtrace", class_info, info_probes_dtrace_command,
> +	   _("\
> +Show information about DTrace static probes.\n\
> +Usage: info probes dtrace [PROVIDER [NAME [OBJECT]]]\n\
> +Each argument is a regular expression, used to select probes.\n\
> +PROVIDER matches probe provider names.\n\
> +NAME matches the probe names.\n\
> +OBJECT matches the executable or shared library name."),
> +	   info_probes_cmdlist_get ());
> +}
> -- 
> 1.7.10.4
  

Patch

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 1da8af6..a237a1f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -800,7 +800,8 @@  SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
 	d-exp.y d-lang.c d-valprint.c \
 	cp-name-parser.y \
-	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
+	dbxread.c demangle.c dictionary.c disasm.c doublest.c \
+	dtrace-probe.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
 	dwarf2-frame-tailcall.c \
 	elfread.c environ.c eval.c event-loop.c event-top.c \
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index cab6c56..ebaa9ce 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -15998,7 +15998,8 @@  all_tracepoints (void)
 command" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]\n\
 PROBE_MODIFIER shall be present if the command is to be placed in a\n\
 probe point.  Accepted values are `-probe' (for a generic, automatically\n\
-guessed probe type) or `-probe-stap' (for a SystemTap probe).\n\
+guessed probe type), `-probe-stap' (for a SystemTap probe) or \n\
+`-probe-dtrace' (for a DTrace probe).\n\
 LOCATION may be a line number, function name, or \"*\" and an address.\n\
 If a line number is specified, break at start of code for that line.\n\
 If a function is specified, break at start of code for that function.\n\
diff --git a/gdb/configure b/gdb/configure
index 1d6d88b..a1660bc 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -13241,7 +13241,7 @@  $as_echo "$gdb_cv_var_elf" >&6; }
   LDFLAGS=$OLD_LDFLAGS
   LIBS=$OLD_LIBS
 if test $gdb_cv_var_elf = yes; then
-  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o"
+  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o"
 
 $as_echo "#define HAVE_ELF 1" >>confdefs.h
 
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 2d73669..4ac5f7b 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -2063,7 +2063,7 @@  AC_SUBST(WIN32LIBS)
 GDB_AC_CHECK_BFD([for ELF support in BFD], gdb_cv_var_elf,
                  [bfd_get_elf_phdr_upper_bound (NULL)], elf-bfd.h)
 if test $gdb_cv_var_elf = yes; then
-  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o"
+  CONFIG_OBS="$CONFIG_OBS elfread.o stap-probe.o dtrace-probe.o"
   AC_DEFINE(HAVE_ELF, 1,
 	    [Define if ELF support should be included.])
   # -ldl is provided by bfd/Makfile.am (LIBDL) <PLUGINS>.
diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
new file mode 100644
index 0000000..f4bfc70
--- /dev/null
+++ b/gdb/dtrace-probe.c
@@ -0,0 +1,909 @@ 
+/* DTrace probe support for GDB.
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   Contributed by Oracle, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "probe.h"
+#include "vec.h"
+#include "elf-bfd.h"
+#include "gdbtypes.h"
+#include "obstack.h"
+#include "objfiles.h"
+#include "complaints.h"
+#include "value.h"
+#include "ax.h"
+#include "ax-gdb.h"
+#include "language.h"
+#include "parser-defs.h"
+#include "inferior.h"
+
+/* The type of the ELF sections where we will find the DOF programs
+   with information about probes.  */
+
+#ifndef SHT_SUNW_dof
+# define SHT_SUNW_dof	0x6ffffff4
+#endif
+
+/* Forward declaration.  */
+
+static const struct probe_ops dtrace_probe_ops;
+
+/* The following structure represents a single argument for the
+   probe.  */
+
+struct dtrace_probe_arg
+{
+  /* The type of the probe argument.  */
+  struct type *type;
+
+  /* A string describing the type.  */
+  char *type_str;
+
+  /* The argument converted to an internal GDB expression.  */
+  struct expression *expr;
+};
+
+typedef struct dtrace_probe_arg dtrace_probe_arg_s;
+DEF_VEC_O (dtrace_probe_arg_s);
+
+/* The following structure represents an enabler for a probe.  */
+
+struct dtrace_probe_enabler
+{
+  /* Program counter where the is-enabled probe is installed.  The
+     contents (nops, whatever...) stored at this address are
+     architecture dependent.  */
+  CORE_ADDR address;
+};
+
+typedef struct dtrace_probe_enabler dtrace_probe_enabler_s;
+DEF_VEC_O (dtrace_probe_enabler_s);
+
+/* The following structure represents a dtrace probe.  */
+
+struct dtrace_probe
+{
+  /* Generic information about the probe.  This must be the first
+     element of this struct, in order to maintain binary compatibility
+     with the `struct probe' and be able to fully abstract it.  */
+  struct probe p;
+
+  /* A probe can have zero or more arguments.  */
+  int probe_argc;
+  VEC (dtrace_probe_arg_s) *args;
+
+  /* A probe can have zero or more "enablers" associated with it.  */
+  VEC (dtrace_probe_enabler_s) *enablers;
+
+  /* Whether the expressions for the arguments have been built.  */
+  unsigned int args_expr_built : 1;
+};
+
+/* Implementation of the probe_is_linespec method.  */
+
+static int
+dtrace_probe_is_linespec (const char **linespecp)
+{
+  static const char *const keywords[] = { "-pdtrace", "-probe-dtrace", NULL };
+
+  return probe_is_linespec_by_keyword (linespecp, keywords);
+}
+
+/* DOF programs can contain an arbitrary number of sections of 26
+   different types.  In order to support DTrace USDT probes we only
+   need to handle a subset of these section types, fortunately.  These
+   section types are defined in the following enumeration.
+
+   See linux/dtrace/dof_defines.h for a complete list of section types
+   along with their values.  */
+
+enum dtrace_dof_sect_type
+{
+  /* Null section.  */
+  DTRACE_DOF_SECT_TYPE_NONE     = 0,
+  /* A dof_ecbdesc_t. */
+  DTRACE_DOF_SECT_TYPE_ECBDESC  = 3,
+  /* A string table.  */
+  DTRACE_DOF_SECT_TYPE_STRTAB   = 8,
+  /* A dof_provider_t  */
+  DTRACE_DOF_SECT_TYPE_PROVIDER = 15,
+  /* Array of dof_probe_t  */
+  DTRACE_DOF_SECT_TYPE_PROBES   = 16,
+  /* An array of probe arg mappings.  */
+  DTRACE_DOF_SECT_TYPE_PRARGS   = 17,
+  /* An array of probe arg offsets.  */
+  DTRACE_DOF_SECT_TYPE_PROFFS   = 18,
+  /* An array of probe is-enabled offsets.  */
+  DTRACE_DOF_SECT_TYPE_PRENOFFS = 26
+};
+
+/* The following collection of data structures map the structure of
+   DOF entities.  Again, we only cover the subset of DOF used to
+   implement USDT probes.
+
+   See linux/dtrace/dof.h header for a complete list of data
+   structures.  */
+
+/* Offsets to index the dofh_ident[] array defined below.  */
+
+enum dtrace_dof_ident
+{
+  /* First byte of the magic number.  */
+  DTRACE_DOF_ID_MAG0     = 0,
+  /* Second byte of the magic number.  */
+  DTRACE_DOF_ID_MAG1     = 1,
+  /* Third byte of the magic number.  */
+  DTRACE_DOF_ID_MAG2     = 2,
+  /* Fourth byte of the magic number.  */
+  DTRACE_DOF_ID_MAG3     = 3,
+  /* An enum_dof_encoding value.  */
+  DTRACE_DOF_ID_ENCODING = 5
+};
+
+/* Possible values for dofh_ident[DOF_ID_ENCODING].  */
+
+enum dtrace_dof_encoding
+{
+  /* The DOF program is little-endian.  */
+  DTRACE_DOF_ENCODE_LSB = 1,
+  /* The DOF program is big-endian.  */
+  DTRACE_DOF_ENCODE_MSB = 2
+};
+
+/* A DOF header, which describes the contents of a DOF program: number
+   of sections, size, etc.  */
+
+struct dtrace_dof_hdr
+{
+  /* Identification bytes (see above). */
+  uint8_t dofh_ident[16];
+  /* File attribute flags (if any). */
+  uint32_t dofh_flags;   
+  /* Size of file header in bytes. */
+  uint32_t dofh_hdrsize; 
+  /* Size of section header in bytes. */
+  uint32_t dofh_secsize; 
+  /* Number of section headers. */
+  uint32_t dofh_secnum;  
+  /* File offset of section headers. */
+  uint64_t dofh_secoff;  
+  /* File size of loadable portion. */
+  uint64_t dofh_loadsz;  
+  /* File size of entire DOF file. */
+  uint64_t dofh_filesz;  
+  /* Reserved for future use. */
+  uint64_t dofh_pad;     
+};
+
+/* A DOF section, whose contents depend on its type.  The several
+   supported section types are described in the enum
+   dtrace_dof_sect_type above.  */
+
+struct dtrace_dof_sect
+{
+  /* Section type (see the define above). */
+  uint32_t dofs_type;
+  /* Section data memory alignment. */
+  uint32_t dofs_align; 
+  /* Section flags (if any). */
+  uint32_t dofs_flags; 
+  /* Size of section entry (if table). */
+  uint32_t dofs_entsize;
+  /* DOF + offset points to the section data. */
+  uint64_t dofs_offset;
+  /* Size of section data in bytes.  */
+  uint64_t dofs_size;  
+};
+
+/* A DOF provider, which is the provider of a probe.  */
+
+struct dtrace_dof_provider
+{
+  /* Link to a DTRACE_DOF_SECT_TYPE_STRTAB section. */
+  uint32_t dofpv_strtab; 
+  /* Link to a DTRACE_DOF_SECT_TYPE_PROBES section. */
+  uint32_t dofpv_probes; 
+  /* Link to a DTRACE_DOF_SECT_TYPE_PRARGS section. */
+  uint32_t dofpv_prargs; 
+  /* Link to a DTRACE_DOF_SECT_TYPE_PROFFS section. */
+  uint32_t dofpv_proffs; 
+  /* Provider name string. */
+  uint32_t dofpv_name;   
+  /* Provider attributes. */
+  uint32_t dofpv_provattr;
+  /* Module attributes. */
+  uint32_t dofpv_modattr; 
+  /* Function attributes. */
+  uint32_t dofpv_funcattr;
+  /* Name attributes. */
+  uint32_t dofpv_nameattr;
+  /* Args attributes. */
+  uint32_t dofpv_argsattr;
+  /* Link to a DTRACE_DOF_SECT_PRENOFFS section. */
+  uint32_t dofpv_prenoffs;
+};
+
+/* A set of DOF probes and is-enabled probes sharing a base address
+   and several attributes.  The particular locations and attributes of
+   each probe are maintained in arrays in several other DOF sections.
+   See the comment in dtrace_process_dof_probe for details on how
+   these attributes are stored.  */
+
+struct dtrace_dof_probe
+{
+  /* Probe base address or offset. */
+  uint64_t dofpr_addr;   
+  /* Probe function string. */
+  uint32_t dofpr_func;   
+  /* Probe name string. */
+  uint32_t dofpr_name;   
+  /* Native argument type strings. */
+  uint32_t dofpr_nargv;  
+  /* Translated argument type strings. */
+  uint32_t dofpr_xargv;  
+  /* Index of first argument mapping. */
+  uint32_t dofpr_argidx; 
+  /* Index of first offset entry. */
+  uint32_t dofpr_offidx; 
+  /* Native argument count. */
+  uint8_t  dofpr_nargc;  
+  /* Translated argument count. */
+  uint8_t  dofpr_xargc;  
+  /* Number of offset entries for probe. */
+  uint16_t dofpr_noffs;  
+  /* Index of first is-enabled offset. */
+  uint32_t dofpr_enoffidx;
+  /* Number of is-enabled offsets. */
+  uint16_t dofpr_nenoffs;
+  /* Reserved for future use. */
+  uint16_t dofpr_pad1;   
+  /* Reserved for future use. */
+  uint32_t dofpr_pad2;   
+};
+
+/* DOF supports two different encodings: MSB (big-endian) and LSB
+   (little-endian).  The encoding is itself encoded in the DOF header.
+   The following function returns an unsigned value in the host
+   endianness.  */
+
+#define DOF_UINT(dof, field)						\
+  extract_unsigned_integer ((gdb_byte *) &(field),			\
+			    sizeof ((field)),				\
+			    (((dof)->dofh_ident[DTRACE_DOF_ID_ENCODING] \
+			      == DTRACE_DOF_ENCODE_MSB)			\
+			     ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE))
+
+/* The following macro applies a given byte offset to a DOF (a pointer
+   to a dtrace_dof_hdr structure) and returns the resulting
+   address.  */
+
+#define DTRACE_DOF_PTR(dof, offset) (&((char *) (dof))[(offset)])
+
+/* The following macro returns a pointer to the beginning of a given
+   section in a DOF object.  The section is referred to by its index
+   in the sections array.  */
+
+#define DTRACE_DOF_SECT(dof, idx)					\
+  ((struct dtrace_dof_sect *)						\
+   DTRACE_DOF_PTR ((dof),						\
+		   DOF_UINT ((dof), (dof)->dofh_secoff)			\
+		   + ((idx) * DOF_UINT ((dof), (dof)->dofh_secsize))))
+
+/* Helper function to examine the probe described by the given PROBE
+   and PROVIDER data structures and add it to the PROBESP vector.
+   STRTAB, OFFTAB, EOFFTAB and ARGTAB are pointers to tables in the
+   DOF program containing the attributes for the probe.  */
+
+static void
+dtrace_process_dof_probe (struct objfile *objfile,
+			  struct gdbarch *gdbarch, VEC (probe_p) **probesp,
+			  struct dtrace_dof_hdr *dof,
+			  struct dtrace_dof_probe *probe,
+			  struct dtrace_dof_provider *provider,
+			  char *strtab, char *offtab, char *eofftab,
+			  char *argtab, uint64_t strtab_size)
+{
+  int i, j, num_probes, num_enablers;
+  struct cleanup *cleanup;
+  VEC (dtrace_probe_enabler_s) *enablers;
+  char *p;
+
+  /* Each probe section can define zero or more probes of two
+     different types:
+
+     - probe->dofpr_noffs regular probes whose program counters are
+       stored in 32bit words starting at probe->dofpr_addr +
+       offtab[probe->dofpr_offidx].
+
+     - probe->dofpr_nenoffs is-enabled probes whose program counters
+       are stored in 32bit words starting at probe->dofpr_addr +
+       eofftab[probe->dofpr_enoffidx].
+
+     However is-enabled probes are not probes per-se, but an
+     optimization hack that is implemented in the kernel in a very
+     similar way than normal probes.  This is how we support
+     is-enabled probes on GDB:
+
+     - Our probes are always DTrace regular probes.
+
+     - Our probes can be associated with zero or more "enablers".  The
+       list of enablers is built from the is-enabled probes defined in
+       the Probe section.
+
+     - Probes having a non-empty list of enablers can be enabled or
+       disabled using the `enable probe' and `disable probe' commands
+       respectively.  The `Enabled' column in the output of `info
+       probes' will read `yes' if the enablers are activated, `no'
+       otherwise.
+
+     - Probes having an empty list of enablers are always enabled.
+       The `Enabled' column in the output of `info probes' will
+       read `always'.
+
+     It follows that if there are DTrace is-enabled probes defined for
+     some provider/name but no DTrace regular probes defined then the
+     GDB user wont be able to enable/disable these conditionals.  */
+
+  num_probes = DOF_UINT (dof, probe->dofpr_noffs);
+  if (num_probes == 0)
+    return;
+
+  /* Build the list of enablers for the probes defined in this Probe
+     DOF section.  */
+  enablers = NULL;
+  cleanup
+    = make_cleanup (VEC_cleanup (dtrace_probe_enabler_s), &enablers);
+  num_enablers = DOF_UINT (dof, probe->dofpr_nenoffs);
+  for (i = 0; i < num_enablers; i++)
+    {
+      struct dtrace_probe_enabler enabler;
+      uint32_t enabler_offset
+	= ((uint32_t *) eofftab)[DOF_UINT (dof, probe->dofpr_enoffidx) + i];
+
+      enabler.address = DOF_UINT (dof, probe->dofpr_addr)
+	+ DOF_UINT (dof, enabler_offset);
+      VEC_safe_push (dtrace_probe_enabler_s, enablers, &enabler);
+    }
+
+  for (i = 0; i < num_probes; i++)
+    {
+      uint32_t probe_offset
+	= ((uint32_t *) offtab)[DOF_UINT (dof, probe->dofpr_offidx) + i];
+      struct dtrace_probe *ret
+	= obstack_alloc (&objfile->per_bfd->storage_obstack, sizeof (*ret));
+
+      ret->p.pops = &dtrace_probe_ops;
+      ret->p.arch = gdbarch;
+      ret->args_expr_built = 0;
+
+      /* Set the provider and the name of the probe.  */
+      ret->p.provider
+	= xstrdup (strtab + DOF_UINT (dof, provider->dofpv_name));
+      ret->p.name = xstrdup (strtab + DOF_UINT (dof, probe->dofpr_name));
+
+      /* The probe address.  */
+      ret->p.address
+	= DOF_UINT (dof, probe->dofpr_addr) + DOF_UINT (dof, probe_offset);
+
+      /* Number of arguments in the probe.  */
+      ret->probe_argc = DOF_UINT (dof, probe->dofpr_nargc);
+
+      /* Store argument type descriptions.  A description of the type
+         of the argument is in the (J+1)th null-terminated string
+         starting at 'strtab' + 'probe->dofpr_nargv'.  */
+      ret->args = NULL;
+      p = strtab + DOF_UINT (dof, probe->dofpr_nargv);
+      for (j = 0; j < ret->probe_argc; j++)
+	{
+	  struct dtrace_probe_arg arg;
+	  struct expression *expr;
+
+	  arg.type_str = xstrdup (p);
+
+	  /* Use strtab_size as a sentinel.  */
+	  while (*p++ != '\0' && p - strtab < strtab_size);
+
+	  /* Try to parse a type expression from the type string.  If
+	     this does not work then we set the type to `long
+	     int'.  */
+          arg.type = builtin_type (gdbarch)->builtin_long;
+	  expr = parse_expression (arg.type_str);
+	  if (expr->elts[0].opcode == OP_TYPE)
+	    arg.type = expr->elts[1].type;
+
+	  VEC_safe_push (dtrace_probe_arg_s, ret->args, &arg);
+	}
+
+      /* Add the vector of enablers to this probe, if any.  */
+      ret->enablers = VEC_copy (dtrace_probe_enabler_s, enablers);
+
+      /* Successfully created probe.  */
+      VEC_safe_push (probe_p, *probesp, (struct probe *) ret);
+    }
+
+  do_cleanups (cleanup);
+}
+
+/* Helper function to collect the probes described in the DOF program
+   whose header is pointed by DOF and add them to the PROBESP vector.
+   SECT is the ELF section containing the DOF program and OBJFILE is
+   its containing object file.  */
+
+static void
+dtrace_process_dof (asection *sect, struct objfile *objfile,
+		    VEC (probe_p) **probesp, struct dtrace_dof_hdr *dof)
+{
+  bfd *abfd = objfile->obfd;
+  int size = bfd_get_arch_size (abfd) / 8;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct dtrace_dof_sect *section;
+  int i;
+
+  /* The first step is to check for the DOF magic number.  If no valid
+     DOF data is found in the section then a complaint is issued to
+     the user and the section skipped.  */
+  if (dof->dofh_ident[DTRACE_DOF_ID_MAG0] != 0x7F
+      || dof->dofh_ident[DTRACE_DOF_ID_MAG1] != 'D'
+      || dof->dofh_ident[DTRACE_DOF_ID_MAG2] != 'O'
+      || dof->dofh_ident[DTRACE_DOF_ID_MAG3] != 'F')
+    goto invalid_dof_data;
+
+  /* Make sure the encoding mark is either DTRACE_DOF_ENCODE_LSB or
+     DTRACE_DOF_ENCODE_MSB.  */
+  if (dof->dofh_ident[DTRACE_DOF_ID_ENCODING] != DTRACE_DOF_ENCODE_LSB
+      && dof->dofh_ident[DTRACE_DOF_ID_ENCODING] != DTRACE_DOF_ENCODE_MSB)
+    goto invalid_dof_data;
+
+  /* Make sure this DOF is not an enabling DOF, i.e. there are no ECB
+     Description sections.  */
+  section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
+						       DOF_UINT (dof, dof->dofh_secoff));
+  for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
+    if (section->dofs_type == DTRACE_DOF_SECT_TYPE_ECBDESC)
+      return;
+
+  /* Iterate over any section of type Provider and extract the probe
+     information from them.  If there are no "provider" sections on
+     the DOF then we just return.  */
+  section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof,
+						       DOF_UINT (dof, dof->dofh_secoff));
+  for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++)
+    if (DOF_UINT (dof, section->dofs_type) == DTRACE_DOF_SECT_TYPE_PROVIDER)
+      {
+	struct dtrace_dof_provider *provider = (struct dtrace_dof_provider *)
+	  DTRACE_DOF_PTR (dof, DOF_UINT (dof, section->dofs_offset));
+	struct dtrace_dof_sect *strtab_s
+	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_strtab));
+	struct dtrace_dof_sect *probes_s
+	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_probes));
+	struct dtrace_dof_sect *args_s
+	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prargs));
+	struct dtrace_dof_sect *offsets_s
+	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_proffs));
+	struct dtrace_dof_sect *eoffsets_s
+	  = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prenoffs));
+	char *strtab  = DTRACE_DOF_PTR (dof, DOF_UINT (dof, strtab_s->dofs_offset));
+	char *offtab  = DTRACE_DOF_PTR (dof, DOF_UINT (dof, offsets_s->dofs_offset));
+	char *eofftab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, eoffsets_s->dofs_offset));
+	char *argtab  = DTRACE_DOF_PTR (dof, DOF_UINT (dof, args_s->dofs_offset));
+	unsigned int entsize = DOF_UINT (dof, probes_s->dofs_entsize);
+	int num_probes;
+
+	/* Very, unlikely, but could crash gdb if not handled
+	   properly.  */
+	if (entsize == 0)
+	  goto invalid_dof_data;
+
+	num_probes = DOF_UINT (dof, probes_s->dofs_size) / entsize;
+
+	for (i = 0; i < num_probes; i++)
+	  {
+	    struct dtrace_dof_probe *probe = (struct dtrace_dof_probe *)
+	      DTRACE_DOF_PTR (dof, DOF_UINT (dof, probes_s->dofs_offset)
+			      + (i * DOF_UINT (dof, probes_s->dofs_entsize)));
+
+	    dtrace_process_dof_probe (objfile,
+				      gdbarch, probesp,
+				      dof, probe,
+				      provider, strtab, offtab, eofftab, argtab,
+				      DOF_UINT (dof, strtab_s->dofs_size));
+	  }
+      }
+
+  return;
+	  
+ invalid_dof_data:
+  complaint (&symfile_complaints,
+	     _("skipping section '%s' which does not contain valid DOF data."),
+	     sect->name);
+}
+
+/* Helper function to build the GDB internal expressiosn that, once
+   evaluated, will calculate the values of the arguments of a given
+   PROBE.  */
+
+static void
+dtrace_build_arg_exprs (struct dtrace_probe *probe,
+			struct gdbarch *gdbarch)
+{
+  struct parser_state pstate;
+  struct dtrace_probe_arg *arg;
+  int i;
+
+  probe->args_expr_built = 1;
+
+  /* Iterate over the arguments in the probe and build the
+     corresponding GDB internal expression that will generate the
+     value of the argument when executed at the PC of the probe.  */
+  for (i = 0; i < probe->probe_argc; i++)
+    {
+      struct cleanup *back_to;
+
+      arg = VEC_index (dtrace_probe_arg_s, probe->args, i);
+
+      /* Initialize the expression buffer in the parser state.  The
+	 language does not matter, since we are using our own
+	 parser.  */
+      initialize_expout (&pstate, 10, current_language, gdbarch);
+      back_to = make_cleanup (free_current_contents, &pstate.expout);
+
+      /* The argument value, which is ABI dependent and casted to
+	 `long int'.  */
+      gdbarch_dtrace_parse_probe_argument (gdbarch, &pstate, i);
+
+      discard_cleanups (back_to);
+
+      /* Casting to the expected type, but only if the type was
+	 recognized at probe load time.  Otherwise the argument will
+	 be evaluated as the long integer passed to the probe.  */
+      if (arg->type != NULL)
+	{
+	  write_exp_elt_opcode (&pstate, UNOP_CAST);
+	  write_exp_elt_type   (&pstate, arg->type);
+	  write_exp_elt_opcode (&pstate, UNOP_CAST);
+	}     
+
+      reallocate_expout (&pstate);
+      arg->expr = pstate.expout;
+      prefixify_expression (arg->expr);
+    }
+}
+
+/* Helper function to return the Nth argument of a given PROBE.  */
+
+static struct dtrace_probe_arg *
+dtrace_get_arg (struct dtrace_probe *probe, unsigned n,
+		struct gdbarch *gdbarch)
+{
+  if (!probe->args_expr_built)
+    dtrace_build_arg_exprs (probe, gdbarch);
+
+  return VEC_index (dtrace_probe_arg_s, probe->args, n);
+}
+
+/* Implementation of the get_probes method.  */
+
+static void
+dtrace_get_probes (VEC (probe_p) **probesp, struct objfile *objfile)
+{
+  bfd *abfd = objfile->obfd;
+  asection *sect = NULL;
+
+  /* Do nothing in case this is a .debug file, instead of the objfile
+     itself.  */
+  if (objfile->separate_debug_objfile_backlink != NULL)
+    return;
+
+  /* Iterate over the sections in OBJFILE looking for DTrace
+     information.  */
+  for (sect = abfd->sections; sect != NULL; sect = sect->next)
+    {
+      if (elf_section_data (sect)->this_hdr.sh_type == SHT_SUNW_dof)
+	{
+	  struct dtrace_dof_hdr *dof;
+
+	  /* Read the contents of the DOF section and then process it to
+	     extract the information of any probe defined into it.  */
+	  if (!bfd_malloc_and_get_section (abfd, sect, (bfd_byte **) &dof))
+	    complaint (&symfile_complaints,
+		       _("could not obtain the contents of"
+			 "section '%s' in objfile `%s'."),
+		       sect->name, abfd->filename);
+      
+	  dtrace_process_dof (sect, objfile, probesp, dof);
+	  xfree (dof);
+	}
+    }
+}
+
+/* Helper function to determine whether a given probe is "enabled" or
+   "disabled".  A disabled probe is a probe in which one or more
+   enablers are disabled.  */
+
+static int
+dtrace_probe_is_enabled (struct dtrace_probe *probe)
+{
+  int i;
+  struct gdbarch *gdbarch = probe->p.arch;
+  struct dtrace_probe_enabler *enabler;
+
+  for (i = 0;
+       VEC_iterate (dtrace_probe_enabler_s, probe->enablers, i, enabler);
+       i++)
+    if (!gdbarch_dtrace_probe_is_enabled (gdbarch, enabler->address))
+      return 0;
+
+  return 1;
+}
+
+/* Implementation of the get_probe_address method.  */
+
+static CORE_ADDR
+dtrace_get_probe_address (struct probe *probe, struct objfile *objfile)
+{
+  gdb_assert (probe->pops == &dtrace_probe_ops);
+  return probe->address + ANOFFSET (objfile->section_offsets,
+				    SECT_OFF_DATA (objfile));
+}
+
+/* Implementation of the get_probe_argument_count method.  */
+
+static unsigned
+dtrace_get_probe_argument_count (struct probe *probe_generic,
+				 struct frame_info *frame)
+{
+  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
+
+  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+  return dtrace_probe->probe_argc;
+}
+
+/* Implementation of the can_evaluate_probe_arguments method.  */
+
+static int
+dtrace_can_evaluate_probe_arguments (struct probe *probe_generic)
+{
+  struct gdbarch *gdbarch = probe_generic->arch;
+
+  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+  return gdbarch_dtrace_parse_probe_argument_p (gdbarch);
+}
+
+/* Implementation of the evaluate_probe_argument method.  */
+
+static struct value *
+dtrace_evaluate_probe_argument (struct probe *probe_generic, unsigned n,
+				struct frame_info *frame)
+{
+  struct gdbarch *gdbarch = probe_generic->arch;
+  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
+  struct dtrace_probe_arg *arg;
+  int pos = 0;
+
+  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+  arg = dtrace_get_arg (dtrace_probe, n, gdbarch);
+  return evaluate_subexp_standard (arg->type, arg->expr, &pos, EVAL_NORMAL);
+}
+
+/* Implementation of the compile_to_ax method.  */
+
+static void
+dtrace_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr,
+		      struct axs_value *value, unsigned n)
+{
+  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic;
+  struct dtrace_probe_arg *arg;
+  union exp_element *pc;
+
+  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+  arg = dtrace_get_arg (dtrace_probe, n, expr->gdbarch);
+
+  pc = arg->expr->elts;
+  gen_expr (arg->expr, &pc, expr, value);
+
+  require_rvalue (expr, value);
+  value->type = arg->type;
+}
+
+/* Implementation of the probe_destroy method.  */
+
+static void
+dtrace_probe_destroy (struct probe *probe_generic)
+{
+  struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
+  struct dtrace_probe_arg *arg;
+  int i;
+
+  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+  for (i = 0; VEC_iterate (dtrace_probe_arg_s, probe->args, i, arg); i++)
+    {
+      xfree (arg->type_str);
+      xfree (arg->expr);
+    }
+
+  VEC_free (dtrace_probe_enabler_s, probe->enablers);
+  VEC_free (dtrace_probe_arg_s, probe->args);
+}
+
+/* Implementation of the type_name method.  */
+
+static const char *
+dtrace_type_name (struct probe *probe_generic)
+{
+  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+  return "dtrace";
+}
+
+/* Implementation of the gen_info_probes_table_header method.  */
+
+static void
+dtrace_gen_info_probes_table_header (VEC (info_probe_column_s) **heads)
+{
+  info_probe_column_s dtrace_probe_column;
+
+  dtrace_probe_column.field_name = "enabled";
+  dtrace_probe_column.print_name = _("Enabled");
+
+  VEC_safe_push (info_probe_column_s, *heads, &dtrace_probe_column);
+}
+
+/* Implementation of the gen_info_probes_table_values method.  */
+
+static void
+dtrace_gen_info_probes_table_values (struct probe *probe_generic,
+				     VEC (const_char_ptr) **ret)
+{
+  struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic;
+  const char *val = NULL;
+
+  gdb_assert (probe_generic->pops == &dtrace_probe_ops);
+
+  if (VEC_empty (dtrace_probe_enabler_s, probe->enablers))
+    val = "always";
+  else if (!gdbarch_dtrace_probe_is_enabled_p (probe_generic->arch))
+    val = "unknown";
+  else if (dtrace_probe_is_enabled (probe))
+    val = "yes";
+  else
+    val = "no";
+
+  VEC_safe_push (const_char_ptr, *ret, val);
+}
+
+/* Implementation of the enable_probe method.  */
+
+static void
+dtrace_enable_probe (struct probe *probe)
+{
+  struct gdbarch *gdbarch = probe->arch;
+  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
+  struct dtrace_probe_enabler *enabler;
+  int i;
+
+  gdb_assert (probe->pops == &dtrace_probe_ops);
+
+  /* Enabling a dtrace probe implies patching the text section of the
+     running process, so make sure the inferior is indeed running.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    error (_("No inferior running"));
+
+  /* Fast path.  */
+  if (dtrace_probe_is_enabled (dtrace_probe))
+    return;
+
+  /* Iterate over all defined enabler in the given probe and enable
+     them all using the corresponding gdbarch hook.  */
+
+  for (i = 0;
+       VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
+       i++)
+    if (gdbarch_dtrace_enable_probe_p (gdbarch))
+      gdbarch_dtrace_enable_probe (gdbarch, enabler->address);
+}
+
+
+/* Implementation of the disable_probe method.  */
+
+static void
+dtrace_disable_probe (struct probe *probe)
+{
+  struct gdbarch *gdbarch = probe->arch;
+  struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe;
+  struct dtrace_probe_enabler *enabler;
+  int i;
+
+  gdb_assert (probe->pops == &dtrace_probe_ops);
+
+  /* Disabling a dtrace probe implies patching the text section of the
+     running process, so make sure the inferior is indeed running.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    error (_("No inferior running"));
+
+  /* Fast path.  */
+  if (!dtrace_probe_is_enabled (dtrace_probe))
+    return;
+
+  /* Are we trying to disable a probe that does not have any enabler
+     associated?  */
+  if (VEC_empty (dtrace_probe_enabler_s, dtrace_probe->enablers))
+    error (_("Probe %s:%s cannot be disabled."), probe->provider, probe->name);
+
+  /* Iterate over all defined enabler in the given probe and disable
+     them all using the corresponding gdbarch hook.  */
+
+  for (i = 0;
+       VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler);
+       i++)
+    {
+      if (gdbarch_dtrace_disable_probe_p (gdbarch))
+	gdbarch_dtrace_disable_probe (gdbarch, enabler->address);
+    }
+}
+
+/* DTrace probe_ops.  */
+
+static const struct probe_ops dtrace_probe_ops =
+{
+  dtrace_probe_is_linespec,
+  dtrace_get_probes,
+  dtrace_get_probe_address,
+  dtrace_get_probe_argument_count,
+  dtrace_can_evaluate_probe_arguments,
+  dtrace_evaluate_probe_argument,
+  dtrace_compile_to_ax,
+  NULL, /* set_semaphore  */
+  NULL, /* clear_semaphore  */
+  dtrace_probe_destroy,
+  dtrace_type_name,
+  dtrace_gen_info_probes_table_header,
+  dtrace_gen_info_probes_table_values,
+  dtrace_enable_probe,
+  dtrace_disable_probe
+};
+
+/* Implementation of the `info probes dtrace' command.  */
+
+static void
+info_probes_dtrace_command (char *arg, int from_tty)
+{
+  info_probes_for_ops (arg, from_tty, &dtrace_probe_ops);
+}
+
+void _initialize_dtrace_probe (void);
+
+void
+_initialize_dtrace_probe (void)
+{
+  VEC_safe_push (probe_ops_cp, all_probe_ops, &dtrace_probe_ops);
+
+  add_cmd ("dtrace", class_info, info_probes_dtrace_command,
+	   _("\
+Show information about DTrace static probes.\n\
+Usage: info probes dtrace [PROVIDER [NAME [OBJECT]]]\n\
+Each argument is a regular expression, used to select probes.\n\
+PROVIDER matches probe provider names.\n\
+NAME matches the probe names.\n\
+OBJECT matches the executable or shared library name."),
+	   info_probes_cmdlist_get ());
+}