From patchwork Mon Nov 13 17:53:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergio Durigan Junior X-Patchwork-Id: 24219 Received: (qmail 96782 invoked by alias); 13 Nov 2017 18:02:26 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 96550 invoked by uid 89); 13 Nov 2017 18:02:26 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, LIKELY_SPAM_BODY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 13 Nov 2017 18:02:23 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7D2984ACBC for ; Mon, 13 Nov 2017 17:53:35 +0000 (UTC) Received: from psique.yyz.redhat.com (unused-10-15-17-193.yyz.redhat.com [10.15.17.193]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3419084401; Mon, 13 Nov 2017 17:53:35 +0000 (UTC) From: Sergio Durigan Junior To: GDB Patches Cc: Sergio Durigan Junior Subject: [PATCH 3/3] Convert DTrace probe interface to C++ (and perform some cleanups) Date: Mon, 13 Nov 2017 12:53:19 -0500 Message-Id: <20171113175319.24280-6-sergiodj@redhat.com> In-Reply-To: <20171113175319.24280-1-sergiodj@redhat.com> References: <20171113175319.24280-1-sergiodj@redhat.com> X-IsSubscribed: yes 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've regtested this patch on BuildBot, no regressions found. gdb/ChangeLog: 2017-11-13 Sergio Durigan Junior * dtrace-probe.c (struct probe_ops dtrace_probe_ops): Delete. (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. (dtrace_static_probe_ops::emit_info_probes_extra_fields): New method. (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'. --- gdb/dtrace-probe.c | 528 +++++++++++++++++++++++++++-------------------------- 1 file changed, 268 insertions(+), 260 deletions(-) diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c index 2bbe03e4b3..b53ff7ac6c 100644 --- a/gdb/dtrace-probe.c +++ b/gdb/dtrace-probe.c @@ -41,10 +41,6 @@ # 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. */ @@ -60,9 +56,6 @@ struct dtrace_probe_arg 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 @@ -73,39 +66,121 @@ 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 *probesp, + struct objfile *objfile) const override; + + /* See probe.h. */ + const char *type_name () const override; + + /* See probe.h. */ + bool emit_info_probes_extra_fields () const override; + + /* See probe.h. */ + void gen_info_probes_table_header + (std::vector *heads) 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 &args_, + std::vector &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) + {} + + /* Destructor for dtrace_probe. */ + ~dtrace_probe () + { + for (struct dtrace_probe_arg arg : m_args) + { + xfree (arg.type_str); + xfree (arg.expr); + } + } + + /* 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. */ + int 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. */ + void gen_info_probes_table_values + (std::vector *values) const override; + + /* See probe.h. */ + bool can_enable () const override + { + return true; + } + + /* 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; + int m_argc; + std::vector m_args; /* A probe can have zero or more "enablers" associated with it. */ - VEC (dtrace_probe_enabler_s) *enablers; + std::vector 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 +397,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 +441,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 enablers; num_enablers = DOF_UINT (dof, probe->dofpr_nenoffs); for (i = 0; i < num_enablers; i++) { @@ -380,38 +451,32 @@ 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 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; @@ -442,17 +507,18 @@ dtrace_process_dof_probe (struct objfile *objfile, if (expr != NULL && expr->elts[0].opcode == OP_TYPE) arg.type = expr->elts[1].type; - VEC_safe_push (dtrace_probe_arg_s, ret->args, &arg); + args.push_back (arg); } - /* Add the vector of enablers to this probe, if any. */ - ret->enablers = VEC_copy (dtrace_probe_enabler_s, enablers); + std::vector enablers_copy = enablers; + dtrace_probe *ret = new dtrace_probe (std::string (name), + std::string (probe_provider), + address, gdbarch, + args, 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 +621,23 @@ 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; + 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 (int i = 0; i < m_argc; i++) { + struct dtrace_probe_arg *arg; struct cleanup *back_to; + struct parser_state pstate; - arg = VEC_index (dtrace_probe_arg_s, probe->args, i); + arg = &m_args[i]; /* Initialize the expression buffer in the parser state. The language does not matter, since we are using our own @@ -606,138 +667,82 @@ dtrace_build_arg_exprs (struct dtrace_probe *probe, } } -/* 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. */ +/* Implementation of 'get_arg_by_number' method. */ -static void -dtrace_get_probes (std::vector *probesp, struct objfile *objfile) +struct dtrace_probe_arg * +dtrace_probe::get_arg_by_number (unsigned n, struct gdbarch *gdbarch) { - 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; + if (!m_args_expr_built) + this->build_arg_exprs (gdbarch); - /* 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); - } - } + return &m_args[n]; } -/* 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. */ +/* Implementation of the probe is_enabled method. */ -static int -dtrace_probe_is_enabled (struct dtrace_probe *probe) +bool +dtrace_probe::is_enabled () const { - int i; - struct gdbarch *gdbarch = probe->p.arch; - struct dtrace_probe_enabler *enabler; + struct gdbarch *gdbarch = this->get_gdbarch (); - 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; + for (struct dtrace_probe_enabler enabler : m_enablers) + if (!gdbarch_dtrace_probe_is_enabled (gdbarch, enabler.address)) + return false; - 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_argc; } -/* 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) +int +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); + arg = this->get_arg_by_number (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) +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); @@ -746,83 +751,40 @@ dtrace_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr, 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. */ +/* Implementation of the 'get_static_ops' method. */ -static const char * -dtrace_type_name (struct probe *probe_generic) +const static_probe_ops * +dtrace_probe::get_static_ops () const { - 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) +void +dtrace_probe::gen_info_probes_table_values + (std::vector *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); + values->push_back (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 +792,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 (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 +816,111 @@ 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 (), this->get_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++) + 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. */ - -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 is_linespec method. */ + +bool +dtrace_static_probe_ops::is_linespec (const char **linespecp) const +{ + 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 *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 'emit_info_probes_extra_fields' method. */ + +bool +dtrace_static_probe_ops::emit_info_probes_extra_fields () const +{ + return true; +} + +/* Implementation of the gen_info_probes_table_header method. */ + +void +dtrace_static_probe_ops::gen_info_probes_table_header + (std::vector *heads) const +{ + struct info_probe_column dtrace_probe_column; + + dtrace_probe_column.field_name = "enabled"; + dtrace_probe_column.print_name = _("Enabled"); + + heads->push_back(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, _("\