diff options
author | Sergio Durigan Junior <sergiodj@redhat.com> | 2017-11-13 01:29:39 -0500 |
---|---|---|
committer | Sergio Durigan Junior <sergiodj@redhat.com> | 2017-11-22 19:13:46 -0500 |
commit | 9c23b42ffa67b866cd7562c1d8caed70db5d6840 (patch) | |
tree | cf9d240bfdec977b0063e2f56ff6cf4df4529172 /gdb/dtrace-probe.c | |
parent | 0e9ae10f5f97824067365af4813b843973297573 (diff) | |
download | fsf-binutils-gdb-9c23b42ffa67b866cd7562c1d8caed70db5d6840.zip fsf-binutils-gdb-9c23b42ffa67b866cd7562c1d8caed70db5d6840.tar.gz fsf-binutils-gdb-9c23b42ffa67b866cd7562c1d8caed70db5d6840.tar.bz2 |
Convert DTrace probe interface to C++ (and perform some cleanups)
This patch converts the DTrace probe
interface (gdb/dtrace-probe.[ch]) to C++, and also performs some
cleanups that were on my TODO list for a while.
The main changes were the conversion of 'struct dtrace_probe' to 'class
dtrace_probe', and a new 'class dtrace_static_probe_ops' to replace the
use of 'dtrace_probe_ops'. Both classes implement the virtual methods
exported by their parents, 'class probe' and 'class static_probe_ops',
respectively. I believe it's now a bit simpler to understand the
logic behind the dtrace-probe interface.
There are several helper functions used to parse parts of a dtrace
probe, and since they are generic and don't need to know about the
probe they're working on, I decided to leave them as simple static
functions (instead of e.g. converting them to class methods).
I've also converted a few uses of "VEC" to "std::vector", which makes
the code simpler and easier to maintain. And, as usual, some cleanups
here and there.
Even though I'm sending a series of patches, they need to be tested
and committed as a single unit, because of inter-dependencies. But it
should be easier to review in separate logical units.
I wasn't able to test these modifications because the current test
framework for DTrace probes is not working. See
<https://sourceware.org/bugzilla/show_bug.cgi?id=22420>.
gdb/ChangeLog:
2017-11-22 Sergio Durigan Junior <sergiodj@redhat.com>
* dtrace-probe.c (struct probe_ops dtrace_probe_ops): Delete.
(struct dtrace_probe_arg) <dtrace_probe_arg>: New constructor.
<type_str>: Convert to 'std::string'.
<expr>: Convert to 'expression_up'.
(dtrace_probe_arg_s): Delete type and VEC.
(dtrace_probe_enabler_s): Likewise.
(struct dtrace_probe): Replace by...
(class dtrace_static_probe_ops): ...this and...
(class dtrace_probe): ...this.
(dtrace_probe_is_linespec): Rename to...
(dtrace_static_probe_ops::is_linespec): ...this. Adjust code
to reflect change.
(dtrace_process_dof_probe): Use 'std::vector' instead of VEC.
Adjust code. Create new instance of 'dtrace_probe'.
(dtrace_build_arg_exprs): Rename to...
(dtrace_probe::build_arg_exprs): ...this. Adjust code to
reflect change.
(dtrace_get_probes): Rename to...
(dtrace_static_probe_ops::get_probes): ...this. Adjust code
to reflect change.
(dtrace_get_arg): Rename to...
(dtrace_probe::get_arg_by_number): ...this. Adjust code to
reflect change.
(dtrace_probe_is_enabled): Rename to...
(dtrace_probe::is_enabled): ...this. Adjust code to reflect
change.
(dtrace_get_probe_address): Rename to...
(dtrace_probe::get_relocated_address): ...this. Adjust code
to reflect change.
(dtrace_get_probe_argument_count): Rename to...
(dtrace_probe::get_argument_count): ...this. Adjust code to
reflect change.
(dtrace_can_evaluate_probe_arguments): Rename to...
(dtrace_probe::can_evaluate_arguments): ...this. Adjust code
to reflect change.
(dtrace_evaluate_probe_argument): Rename to...
(dtrace_probe::evaluate_argument): ...this. Adjust code to
reflect change.
(dtrace_compile_to_ax): Rename to...
(dtrace_probe::compile_to_ax): ...this. Adjust code to
reflect change.
(dtrace_probe_destroy): Delete.
(dtrace_type_name): Rename to...
(dtrace_static_probe_ops::type_name): ...this. Adjust code to
reflect change.
(dtrace_probe::get_static_ops): New method.
(dtrace_gen_info_probes_table_header): Rename to...
(dtrace_static_probe_ops::gen_info_probes_table_header):
...this. Adjust code to reflect change.
(dtrace_gen_info_probes_table_values): Rename to...
(dtrace_probe::gen_info_probes_table_values): ...this. Adjust
code to reflect change.
(dtrace_enable_probe): Rename to...
(dtrace_probe::enable_probe): ...this. Adjust code to reflect
change.
(dtrace_disable_probe): Rename to...
(dtrace_probe::disable_probe): ...this. Adjust code to reflect
change.
(struct probe_ops dtrace_probe_ops): Delete.
(info_probes_dtrace_command): Call 'info_probes_for_spops'
instead of 'info_probes_for_ops'.
(_initialize_dtrace_probe): Use 'all_static_probe_ops' instead
of 'all_probe_ops'.
Diffstat (limited to 'gdb/dtrace-probe.c')
-rw-r--r-- | gdb/dtrace-probe.c | 550 |
1 files changed, 274 insertions, 276 deletions
diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c index 2bbe03e..ace3d30 100644 --- a/gdb/dtrace-probe.c +++ b/gdb/dtrace-probe.c @@ -41,28 +41,27 @@ # define SHT_SUNW_dof 0x6ffffff4 #endif -/* Forward declaration. */ - -extern const struct probe_ops dtrace_probe_ops; - /* The following structure represents a single argument for the probe. */ struct dtrace_probe_arg { + dtrace_probe_arg (struct type *type_, std::string &&type_str_, + expression_up &&expr_) + : type (type_), type_str (std::move (type_str_)), + expr (std::move (expr_)) + {} + /* The type of the probe argument. */ struct type *type; /* A string describing the type. */ - char *type_str; + std::string type_str; /* The argument converted to an internal GDB expression. */ - struct expression *expr; + expression_up 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 @@ -73,39 +72,106 @@ struct dtrace_probe_enabler CORE_ADDR address; }; -typedef struct dtrace_probe_enabler dtrace_probe_enabler_s; -DEF_VEC_O (dtrace_probe_enabler_s); +/* Class that implements the static probe methods for "stap" probes. */ + +class dtrace_static_probe_ops : public static_probe_ops +{ +public: + /* See probe.h. */ + bool is_linespec (const char **linespecp) const override; + + /* See probe.h. */ + void get_probes (std::vector<probe *> *probesp, + struct objfile *objfile) const override; + + /* See probe.h. */ + const char *type_name () const override; + + /* See probe.h. */ + bool can_enable () const override + { + return true; + } + + /* See probe.h. */ + std::vector<struct info_probe_column> gen_info_probes_table_header + () const override; +}; + +/* DTrace static_probe_ops. */ + +const dtrace_static_probe_ops dtrace_static_probe_ops; /* The following structure represents a dtrace probe. */ -struct dtrace_probe +class dtrace_probe : public 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; - +public: + /* Constructor for dtrace_probe. */ + dtrace_probe (std::string &&name_, std::string &&provider_, CORE_ADDR address_, + struct gdbarch *arch_, + std::vector<struct dtrace_probe_arg> &&args_, + std::vector<struct dtrace_probe_enabler> &&enablers_) + : probe (std::move (name_), std::move (provider_), address_, arch_), + m_args (std::move (args_)), + m_enablers (std::move (enablers_)), + m_args_expr_built (false) + {} + + /* See probe.h. */ + CORE_ADDR get_relocated_address (struct objfile *objfile) override; + + /* See probe.h. */ + unsigned get_argument_count (struct frame_info *frame) override; + + /* See probe.h. */ + bool can_evaluate_arguments () const override; + + /* See probe.h. */ + struct value *evaluate_argument (unsigned n, + struct frame_info *frame) override; + + /* See probe.h. */ + void compile_to_ax (struct agent_expr *aexpr, + struct axs_value *axs_value, + unsigned n) override; + + /* See probe.h. */ + const static_probe_ops *get_static_ops () const override; + + /* See probe.h. */ + std::vector<const char *> gen_info_probes_table_values () const override; + + /* See probe.h. */ + void enable () override; + + /* See probe.h. */ + void disable () override; + + /* Return the Nth argument of the probe. */ + struct dtrace_probe_arg *get_arg_by_number (unsigned n, + struct gdbarch *gdbarch); + + /* Build the GDB internal expressiosn that, once evaluated, will + calculate the values of the arguments of the probe. */ + void build_arg_exprs (struct gdbarch *gdbarch); + + /* Determine whether the probe is "enabled" or "disabled". A + disabled probe is a probe in which one or more enablers are + disabled. */ + bool is_enabled () const; + +private: /* A probe can have zero or more arguments. */ - int probe_argc; - VEC (dtrace_probe_arg_s) *args; + std::vector<struct dtrace_probe_arg> m_args; /* A probe can have zero or more "enablers" associated with it. */ - VEC (dtrace_probe_enabler_s) *enablers; + std::vector<struct dtrace_probe_enabler> m_enablers; /* Whether the expressions for the arguments have been built. */ - unsigned int args_expr_built : 1; + bool m_args_expr_built; }; -/* 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 @@ -322,8 +388,6 @@ dtrace_process_dof_probe (struct objfile *objfile, 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 @@ -368,9 +432,7 @@ dtrace_process_dof_probe (struct objfile *objfile, /* 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); + std::vector<struct dtrace_probe_enabler> enablers; num_enablers = DOF_UINT (dof, probe->dofpr_nenoffs); for (i = 0; i < num_enablers; i++) { @@ -380,46 +442,38 @@ dtrace_process_dof_probe (struct objfile *objfile, enabler.address = DOF_UINT (dof, probe->dofpr_addr) + DOF_UINT (dof, enabler_offset); - VEC_safe_push (dtrace_probe_enabler_s, enablers, &enabler); + enablers.push_back (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 = - XOBNEW (&objfile->per_bfd->storage_obstack, struct dtrace_probe); - - 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)); + const char *probe_provider + = strtab + DOF_UINT (dof, provider->dofpv_name); + const char *name = strtab + DOF_UINT (dof, probe->dofpr_name); /* The probe address. */ - ret->p.address + CORE_ADDR 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); + int 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; + std::vector<struct dtrace_probe_arg> args; p = strtab + DOF_UINT (dof, probe->dofpr_nargv); - for (j = 0; j < ret->probe_argc; j++) + for (j = 0; j < probe_argc; j++) { - struct dtrace_probe_arg arg; expression_up expr; /* Set arg.expr to ensure all fields in expr are initialized and the compiler will not warn when arg is used. */ - arg.expr = NULL; - arg.type_str = xstrdup (p); + std::string type_str (p); /* Use strtab_size as a sentinel. */ while (*p++ != '\0' && p - strtab < strtab_size) @@ -428,11 +482,13 @@ dtrace_process_dof_probe (struct objfile *objfile, /* 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; + struct type *type = builtin_type (gdbarch)->builtin_long; TRY { - expr = parse_expression_with_language (arg.type_str, language_c); + expression_up expr + = parse_expression_with_language (type_str.c_str (), + language_c); } CATCH (ex, RETURN_MASK_ERROR) { @@ -440,19 +496,21 @@ dtrace_process_dof_probe (struct objfile *objfile, END_CATCH if (expr != NULL && expr->elts[0].opcode == OP_TYPE) - arg.type = expr->elts[1].type; + type = expr->elts[1].type; - VEC_safe_push (dtrace_probe_arg_s, ret->args, &arg); + args.emplace_back (type, std::move (type_str), std::move (expr)); } - /* Add the vector of enablers to this probe, if any. */ - ret->enablers = VEC_copy (dtrace_probe_enabler_s, enablers); + std::vector<struct dtrace_probe_enabler> enablers_copy = enablers; + dtrace_probe *ret = new dtrace_probe (std::string (name), + std::string (probe_provider), + address, gdbarch, + std::move (args), + std::move (enablers_copy)); /* Successfully created probe. */ - probesp->push_back ((struct probe *) ret); + probesp->push_back (ret); } - - do_cleanups (cleanup); } /* Helper function to collect the probes described in the DOF program @@ -555,28 +613,21 @@ dtrace_process_dof (asection *sect, struct objfile *objfile, sect->name); } -/* Helper function to build the GDB internal expressiosn that, once - evaluated, will calculate the values of the arguments of a given - PROBE. */ +/* Implementation of 'build_arg_exprs' method. */ -static void -dtrace_build_arg_exprs (struct dtrace_probe *probe, - struct gdbarch *gdbarch) +void +dtrace_probe::build_arg_exprs (struct gdbarch *gdbarch) { - struct parser_state pstate; - struct dtrace_probe_arg *arg; - int i; - - probe->args_expr_built = 1; + size_t argc = 0; + m_args_expr_built = true; /* 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++) + for (struct dtrace_probe_arg &arg : m_args) { struct cleanup *back_to; - - arg = VEC_index (dtrace_probe_arg_s, probe->args, i); + struct parser_state pstate; /* Initialize the expression buffer in the parser state. The language does not matter, since we are using our own @@ -586,243 +637,153 @@ dtrace_build_arg_exprs (struct dtrace_probe *probe, /* The argument value, which is ABI dependent and casted to `long int'. */ - gdbarch_dtrace_parse_probe_argument (gdbarch, &pstate, i); + gdbarch_dtrace_parse_probe_argument (gdbarch, &pstate, argc); 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) + if (arg.type != NULL) { write_exp_elt_opcode (&pstate, UNOP_CAST); - write_exp_elt_type (&pstate, arg->type); + 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); + arg.expr = expression_up (pstate.expout); + prefixify_expression (arg.expr.get ()); + ++argc; } } -/* Helper function to return the Nth argument of a given PROBE. */ +/* Implementation of 'get_arg_by_number' method. */ -static struct dtrace_probe_arg * -dtrace_get_arg (struct dtrace_probe *probe, unsigned n, - struct gdbarch *gdbarch) +struct dtrace_probe_arg * +dtrace_probe::get_arg_by_number (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); + if (!m_args_expr_built) + this->build_arg_exprs (gdbarch); + + if (n > m_args.size ()) + internal_error (__FILE__, __LINE__, + _("Probe '%s' has %d arguments, but GDB is requesting\n" + "argument %u. This should not happen. Please\n" + "report this bug."), + this->get_name ().c_str (), + (int) m_args.size (), n); + + return &m_args[n]; } -/* Implementation of the get_probes method. */ +/* Implementation of the probe is_enabled method. */ -static void -dtrace_get_probes (std::vector<probe *> *probesp, struct objfile *objfile) +bool +dtrace_probe::is_enabled () const { - bfd *abfd = objfile->obfd; - asection *sect = NULL; + struct gdbarch *gdbarch = this->get_gdbarch (); - /* Do nothing in case this is a .debug file, instead of the objfile - itself. */ - if (objfile->separate_debug_objfile_backlink != NULL) - return; + for (const struct dtrace_probe_enabler &enabler : m_enablers) + if (!gdbarch_dtrace_probe_is_enabled (gdbarch, enabler.address)) + return false; - /* 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) - { - bfd_byte *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, &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, - (struct dtrace_dof_hdr *) 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; + return true; } /* Implementation of the get_probe_address method. */ -static CORE_ADDR -dtrace_get_probe_address (struct probe *probe, struct objfile *objfile) +CORE_ADDR +dtrace_probe::get_relocated_address (struct objfile *objfile) { - gdb_assert (probe->pops == &dtrace_probe_ops); - return probe->address + ANOFFSET (objfile->section_offsets, - SECT_OFF_DATA (objfile)); + return this->get_address () + ANOFFSET (objfile->section_offsets, + SECT_OFF_DATA (objfile)); } -/* Implementation of the get_probe_argument_count method. */ +/* Implementation of the get_argument_count method. */ -static unsigned -dtrace_get_probe_argument_count (struct probe *probe_generic, - struct frame_info *frame) +unsigned +dtrace_probe::get_argument_count (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; + return m_args.size (); } -/* Implementation of the can_evaluate_probe_arguments method. */ +/* Implementation of the can_evaluate_arguments method. */ -static int -dtrace_can_evaluate_probe_arguments (struct probe *probe_generic) +bool +dtrace_probe::can_evaluate_arguments () const { - struct gdbarch *gdbarch = probe_generic->arch; + struct gdbarch *gdbarch = this->get_gdbarch (); - gdb_assert (probe_generic->pops == &dtrace_probe_ops); return gdbarch_dtrace_parse_probe_argument_p (gdbarch); } -/* Implementation of the evaluate_probe_argument method. */ +/* Implementation of the evaluate_argument method. */ -static struct value * -dtrace_evaluate_probe_argument (struct probe *probe_generic, unsigned n, - struct frame_info *frame) +struct value * +dtrace_probe::evaluate_argument (unsigned n, + struct frame_info *frame) { - struct gdbarch *gdbarch = probe_generic->arch; - struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic; + struct gdbarch *gdbarch = this->get_gdbarch (); 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); + arg = this->get_arg_by_number (n, gdbarch); + return evaluate_subexp_standard (arg->type, arg->expr.get (), &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) +void +dtrace_probe::compile_to_ax (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); + arg = this->get_arg_by_number (n, expr->gdbarch); pc = arg->expr->elts; - gen_expr (arg->expr, &pc, expr, value); + gen_expr (arg->expr.get (), &pc, expr, value); require_rvalue (expr, value); value->type = arg->type; } -/* Implementation of the probe_destroy method. */ +/* Implementation of the 'get_static_ops' method. */ -static void -dtrace_probe_destroy (struct probe *probe_generic) +const static_probe_ops * +dtrace_probe::get_static_ops () const { - 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); + return &dtrace_static_probe_ops; } /* 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) +std::vector<const char *> +dtrace_probe::gen_info_probes_table_values () const { - 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)) + if (m_enablers.empty ()) val = "always"; - else if (!gdbarch_dtrace_probe_is_enabled_p (probe_generic->arch)) + else if (!gdbarch_dtrace_probe_is_enabled_p (this->get_gdbarch ())) val = "unknown"; - else if (dtrace_probe_is_enabled (probe)) + else if (this->is_enabled ()) val = "yes"; else val = "no"; - VEC_safe_push (const_char_ptr, *ret, val); + return std::vector<const char *> { val }; } -/* Implementation of the enable_probe method. */ +/* Implementation of the enable method. */ -static void -dtrace_enable_probe (struct probe *probe) +void +dtrace_probe::enable () { - 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); + struct gdbarch *gdbarch = this->get_gdbarch (); /* Enabling a dtrace probe implies patching the text section of the running process, so make sure the inferior is indeed running. */ @@ -830,31 +791,23 @@ dtrace_enable_probe (struct probe *probe) error (_("No inferior running")); /* Fast path. */ - if (dtrace_probe_is_enabled (dtrace_probe)) + if (this->is_enabled ()) 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++) + for (const struct dtrace_probe_enabler &enabler : m_enablers) if (gdbarch_dtrace_enable_probe_p (gdbarch)) - gdbarch_dtrace_enable_probe (gdbarch, enabler->address); + gdbarch_dtrace_enable_probe (gdbarch, enabler.address); } /* Implementation of the disable_probe method. */ -static void -dtrace_disable_probe (struct probe *probe) +void +dtrace_probe::disable () { - 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); + struct gdbarch *gdbarch = this->get_gdbarch (); /* Disabling a dtrace probe implies patching the text section of the running process, so make sure the inferior is indeed running. */ @@ -862,57 +815,102 @@ dtrace_disable_probe (struct probe *probe) error (_("No inferior running")); /* Fast path. */ - if (!dtrace_probe_is_enabled (dtrace_probe)) + if (!this->is_enabled ()) 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: no enablers."), probe->provider, probe->name); + if (m_enablers.empty ()) + error (_("Probe %s:%s cannot be disabled: no enablers."), + this->get_provider ().c_str (), this->get_name ().c_str ()); /* 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++) + for (struct dtrace_probe_enabler &enabler : m_enablers) if (gdbarch_dtrace_disable_probe_p (gdbarch)) - gdbarch_dtrace_disable_probe (gdbarch, enabler->address); + gdbarch_dtrace_disable_probe (gdbarch, enabler.address); } -/* DTrace probe_ops. */ +/* Implementation of the is_linespec method. */ -const struct probe_ops dtrace_probe_ops = +bool +dtrace_static_probe_ops::is_linespec (const char **linespecp) const { - 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 -}; + static const char *const keywords[] = { "-pdtrace", "-probe-dtrace", NULL }; + + return probe_is_linespec_by_keyword (linespecp, keywords); +} + +/* Implementation of the get_probes method. */ + +void +dtrace_static_probe_ops::get_probes (std::vector<probe *> *probesp, + struct objfile *objfile) const +{ + 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) + { + bfd_byte *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, &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, + (struct dtrace_dof_hdr *) dof); + xfree (dof); + } + } +} + +/* Implementation of the type_name method. */ + +const char * +dtrace_static_probe_ops::type_name () const +{ + return "dtrace"; +} + +/* Implementation of the gen_info_probes_table_header method. */ + +std::vector<struct info_probe_column> +dtrace_static_probe_ops::gen_info_probes_table_header () const +{ + struct info_probe_column dtrace_probe_column; + + dtrace_probe_column.field_name = "enabled"; + dtrace_probe_column.print_name = _("Enabled"); + + return std::vector<struct info_probe_column> { dtrace_probe_column }; +} /* Implementation of the `info probes dtrace' command. */ static void info_probes_dtrace_command (const char *arg, int from_tty) { - info_probes_for_ops (arg, from_tty, &dtrace_probe_ops); + info_probes_for_spops (arg, from_tty, &dtrace_static_probe_ops); } void _initialize_dtrace_probe (void) { - all_probe_ops.push_back (&dtrace_probe_ops); + all_static_probe_ops.push_back (&dtrace_static_probe_ops); add_cmd ("dtrace", class_info, info_probes_dtrace_command, _("\ |