X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=gdb%2Fprobe.c;h=7bc75d8e879bd8cd0932827716cec46c1d13f6d1;hb=HEAD;hp=ba409591263b3add291c31414836fa01315a04bc;hpb=2dc0e219715356c6acbc3bea85ddec288f752f1f;p=thirdparty%2Fbinutils-gdb.git diff --git a/gdb/probe.c b/gdb/probe.c index ba409591263..b13baf00e71 100644 --- a/gdb/probe.c +++ b/gdb/probe.c @@ -1,6 +1,6 @@ /* Generic static probe support for GDB. - Copyright (C) 2012-2017 Free Software Foundation, Inc. + Copyright (C) 2012-2024 Free Software Foundation, Inc. This file is part of GDB. @@ -17,7 +17,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "defs.h" #include "probe.h" #include "command.h" #include "cli/cli-cmds.h" @@ -27,7 +26,7 @@ #include "progspace.h" #include "filenames.h" #include "linespec.h" -#include "gdb_regex.h" +#include "gdbsupport/gdb_regex.h" #include "frame.h" #include "arch-utils.h" #include "value.h" @@ -36,22 +35,44 @@ #include "location.h" #include #include -#include "common/gdb_optional.h" +#include + +/* Class that implements the static probe methods for "any" probe. */ + +class any_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. */ + std::vector gen_info_probes_table_header + () const override; +}; + +/* Static operations associated with a generic probe. */ + +const any_static_probe_ops any_static_probe_ops {}; /* A helper for parse_probes that decodes a probe specification in SEARCH_PSPACE. It appends matching SALs to RESULT. */ static void -parse_probes_in_pspace (const struct probe_ops *probe_ops, +parse_probes_in_pspace (const static_probe_ops *spops, struct program_space *search_pspace, const char *objfile_namestr, const char *provider, const char *name, std::vector *result) { - struct objfile *objfile; - - ALL_PSPACE_OBJFILES (search_pspace, objfile) + for (objfile *objfile : search_pspace->objfiles ()) { if (!objfile->sf || !objfile->sf->sym_probe_fns) continue; @@ -62,26 +83,26 @@ parse_probes_in_pspace (const struct probe_ops *probe_ops, objfile_namestr) != 0) continue; - const std::vector &probes + const std::vector> &probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (probe *p : probes) + for (auto &p : probes) { - if (probe_ops != &probe_ops_any && p->pops != probe_ops) + if (spops != &any_static_probe_ops && p->get_static_ops () != spops) continue; - if (provider && strcmp (p->provider, provider) != 0) + if (provider != NULL && p->get_provider () != provider) continue; - if (strcmp (p->name, name) != 0) + if (p->get_name () != name) continue; symtab_and_line sal; - sal.pc = get_probe_address (p, objfile); + sal.pc = p->get_relocated_address (objfile); sal.explicit_pc = 1; sal.section = find_pc_overlay (sal.pc); sal.pspace = search_pspace; - sal.probe = p; + sal.prob = p.get (); sal.objfile = objfile; result->push_back (std::move (sal)); @@ -92,21 +113,20 @@ parse_probes_in_pspace (const struct probe_ops *probe_ops, /* See definition in probe.h. */ std::vector -parse_probes (const struct event_location *location, +parse_probes (const location_spec *locspec, struct program_space *search_pspace, struct linespec_result *canonical) { char *arg_end, *arg; char *objfile_namestr = NULL, *provider = NULL, *name, *p; - const struct probe_ops *probe_ops; const char *arg_start, *cs; - gdb_assert (event_location_type (location) == PROBE_LOCATION); - arg_start = get_probe_location (location); + gdb_assert (locspec->type () == PROBE_LOCATION_SPEC); + arg_start = locspec->to_string (); cs = arg_start; - probe_ops = probe_linespec_to_ops (&cs); - if (probe_ops == NULL) + const static_probe_ops *spops = probe_linespec_to_static_ops (&cs); + if (spops == NULL) error (_("'%s' is not a probe linespec"), arg_start); arg = (char *) cs; @@ -159,15 +179,13 @@ parse_probes (const struct event_location *location, std::vector result; if (search_pspace != NULL) { - parse_probes_in_pspace (probe_ops, search_pspace, objfile_namestr, + parse_probes_in_pspace (spops, search_pspace, objfile_namestr, provider, name, &result); } else { - struct program_space *pspace; - - ALL_PSPACES (pspace) - parse_probes_in_pspace (probe_ops, pspace, objfile_namestr, + for (struct program_space *pspace : program_spaces) + parse_probes_in_pspace (spops, pspace, objfile_namestr, provider, name, &result); } @@ -185,7 +203,7 @@ parse_probes (const struct event_location *location, std::string canon (arg_start, arg_end - arg_start); canonical->special_display = 1; canonical->pre_expanded = 1; - canonical->location = new_probe_location (canon.c_str ()); + canonical->locspec = new_probe_location_spec (std::move (canon)); } return result; @@ -193,26 +211,26 @@ parse_probes (const struct event_location *location, /* See definition in probe.h. */ -VEC (probe_p) * +std::vector find_probes_in_objfile (struct objfile *objfile, const char *provider, const char *name) { - VEC (probe_p) *result = NULL; + std::vector result; if (!objfile->sf || !objfile->sf->sym_probe_fns) - return NULL; + return result; - const std::vector &probes + const std::vector> &probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (probe *p : probes) + for (auto &p : probes) { - if (strcmp (p->provider, provider) != 0) + if (p->get_provider () != provider) continue; - if (strcmp (p->name, name) != 0) + if (p->get_name () != name) continue; - VEC_safe_push (probe_p, result, p); + result.push_back (p.get ()); } return result; @@ -223,29 +241,28 @@ find_probes_in_objfile (struct objfile *objfile, const char *provider, struct bound_probe find_probe_by_pc (CORE_ADDR pc) { - struct objfile *objfile; struct bound_probe result; result.objfile = NULL; - result.probe = NULL; + result.prob = NULL; - ALL_OBJFILES (objfile) - { - if (!objfile->sf || !objfile->sf->sym_probe_fns - || objfile->sect_index_text == -1) - continue; - - /* If this proves too inefficient, we can replace with a hash. */ - const std::vector &probes - = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (probe *p : probes) - if (get_probe_address (p, objfile) == pc) - { - result.objfile = objfile; - result.probe = p; - return result; - } - } + for (objfile *objfile : current_program_space->objfiles ()) + { + if (!objfile->sf || !objfile->sf->sym_probe_fns + || objfile->sect_index_text == -1) + continue; + + /* If this proves too inefficient, we can replace with a hash. */ + const std::vector> &probes + = objfile->sf->sym_probe_fns->sym_get_probes (objfile); + for (auto &p : probes) + if (p->get_relocated_address (objfile) == pc) + { + result.objfile = objfile; + result.prob = p.get (); + return result; + } + } return result; } @@ -253,16 +270,16 @@ find_probe_by_pc (CORE_ADDR pc) /* Make a vector of probes matching OBJNAME, PROVIDER, and PROBE_NAME. - If POPS is not NULL, only probes of this certain probe_ops will match. - Each argument is a regexp, or NULL, which matches anything. */ + If SPOPS is not &any_static_probe_ops, only probes related to this + specific static probe ops will match. Each argument is a regexp, + or NULL, which matches anything. */ static std::vector collect_probes (const std::string &objname, const std::string &provider, - const std::string &probe_name, const struct probe_ops *pops) + const std::string &probe_name, const static_probe_ops *spops) { - struct objfile *objfile; std::vector result; - gdb::optional obj_pat, prov_pat, probe_pat; + std::optional obj_pat, prov_pat, probe_pat; if (!provider.empty ()) prov_pat.emplace (provider.c_str (), REG_NOSUB, @@ -274,7 +291,7 @@ collect_probes (const std::string &objname, const std::string &provider, obj_pat.emplace (objname.c_str (), REG_NOSUB, _("Invalid object file regexp")); - ALL_OBJFILES (objfile) + for (objfile *objfile : current_program_space->objfiles ()) { if (! objfile->sf || ! objfile->sf->sym_probe_fns) continue; @@ -285,23 +302,23 @@ collect_probes (const std::string &objname, const std::string &provider, continue; } - const std::vector &probes + const std::vector> &probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (probe *p : probes) + for (auto &p : probes) { - if (pops != NULL && p->pops != pops) + if (spops != &any_static_probe_ops && p->get_static_ops () != spops) continue; if (prov_pat - && prov_pat->exec (p->provider, 0, NULL, 0) != 0) + && prov_pat->exec (p->get_provider ().c_str (), 0, NULL, 0) != 0) continue; if (probe_pat - && probe_pat->exec (p->name, 0, NULL, 0) != 0) + && probe_pat->exec (p->get_name ().c_str (), 0, NULL, 0) != 0) continue; - result.emplace_back (p, objfile); + result.emplace_back (p.get (), objfile); } } @@ -315,16 +332,16 @@ compare_probes (const bound_probe &a, const bound_probe &b) { int v; - v = strcmp (a.probe->provider, b.probe->provider); + v = a.prob->get_provider ().compare (b.prob->get_provider ()); if (v != 0) return v < 0; - v = strcmp (a.probe->name, b.probe->name); + v = a.prob->get_name ().compare (b.prob->get_name ()); if (v != 0) return v < 0; - if (a.probe->address != b.probe->address) - return a.probe->address < b.probe->address; + if (a.prob->get_address () != b.prob->get_address ()) + return a.prob->get_address () < b.prob->get_address (); return strcmp (objfile_name (a.objfile), objfile_name (b.objfile)) < 0; } @@ -334,56 +351,33 @@ compare_probes (const bound_probe &a, const bound_probe &b) static void gen_ui_out_table_header_info (const std::vector &probes, - const struct probe_ops *p) + const static_probe_ops *spops) { /* `headings' refers to the names of the columns when printing `info probes'. */ - VEC (info_probe_column_s) *headings = NULL; - struct cleanup *c; - info_probe_column_s *column; - size_t headings_size; - int ix; - - gdb_assert (p != NULL); - - if (p->gen_info_probes_table_header == NULL - && p->gen_info_probes_table_values == NULL) - return; - - gdb_assert (p->gen_info_probes_table_header != NULL - && p->gen_info_probes_table_values != NULL); + gdb_assert (spops != NULL); - c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings); - p->gen_info_probes_table_header (&headings); + std::vector headings + = spops->gen_info_probes_table_header (); - headings_size = VEC_length (info_probe_column_s, headings); - - for (ix = 0; - VEC_iterate (info_probe_column_s, headings, ix, column); - ++ix) + for (const info_probe_column &column : headings) { - size_t size_max = strlen (column->print_name); + size_t size_max = strlen (column.print_name); for (const bound_probe &probe : probes) { /* `probe_fields' refers to the values of each new field that this probe will display. */ - VEC (const_char_ptr) *probe_fields = NULL; - struct cleanup *c2; - const char *val; - int kx; - if (probe.probe->pops != p) + if (probe.prob->get_static_ops () != spops) continue; - c2 = make_cleanup (VEC_cleanup (const_char_ptr), &probe_fields); - p->gen_info_probes_table_values (probe.probe, &probe_fields); + std::vector probe_fields + = probe.prob->gen_info_probes_table_values (); - gdb_assert (VEC_length (const_char_ptr, probe_fields) - == headings_size); + gdb_assert (probe_fields.size () == headings.size ()); - for (kx = 0; VEC_iterate (const_char_ptr, probe_fields, kx, val); - ++kx) + for (const char *val : probe_fields) { /* It is valid to have a NULL value here, which means that the backend does not have something to write and this particular @@ -393,128 +387,75 @@ gen_ui_out_table_header_info (const std::vector &probes, size_max = std::max (strlen (val), size_max); } - do_cleanups (c2); } current_uiout->table_header (size_max, ui_left, - column->field_name, column->print_name); + column.field_name, column.print_name); } - - do_cleanups (c); } /* Helper function to print not-applicable strings for all the extra - columns defined in a probe_ops. */ + columns defined in a static_probe_ops. */ static void -print_ui_out_not_applicables (const struct probe_ops *pops) +print_ui_out_not_applicables (const static_probe_ops *spops) { - struct cleanup *c; - VEC (info_probe_column_s) *headings = NULL; - info_probe_column_s *column; - int ix; - - if (pops->gen_info_probes_table_header == NULL) - return; - - c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings); - pops->gen_info_probes_table_header (&headings); - - for (ix = 0; - VEC_iterate (info_probe_column_s, headings, ix, column); - ++ix) - current_uiout->field_string (column->field_name, _("n/a")); + std::vector headings + = spops->gen_info_probes_table_header (); - do_cleanups (c); + for (const info_probe_column &column : headings) + current_uiout->field_string (column.field_name, _("n/a")); } /* Helper function to print extra information about a probe and an objfile represented by PROBE. */ static void -print_ui_out_info (struct probe *probe) +print_ui_out_info (probe *probe) { - int ix; - int j = 0; /* `values' refers to the actual values of each new field in the output of `info probe'. `headings' refers to the names of each new field. */ - VEC (const_char_ptr) *values = NULL; - VEC (info_probe_column_s) *headings = NULL; - info_probe_column_s *column; - struct cleanup *c; - gdb_assert (probe != NULL); - gdb_assert (probe->pops != NULL); - - if (probe->pops->gen_info_probes_table_header == NULL - && probe->pops->gen_info_probes_table_values == NULL) - return; - - gdb_assert (probe->pops->gen_info_probes_table_header != NULL - && probe->pops->gen_info_probes_table_values != NULL); - - c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings); - make_cleanup (VEC_cleanup (const_char_ptr), &values); - - probe->pops->gen_info_probes_table_header (&headings); - probe->pops->gen_info_probes_table_values (probe, &values); + std::vector headings + = probe->get_static_ops ()->gen_info_probes_table_header (); + std::vector values + = probe->gen_info_probes_table_values (); - gdb_assert (VEC_length (info_probe_column_s, headings) - == VEC_length (const_char_ptr, values)); + gdb_assert (headings.size () == values.size ()); - for (ix = 0; - VEC_iterate (info_probe_column_s, headings, ix, column); - ++ix) + for (int ix = 0; ix < headings.size (); ++ix) { - const char *val = VEC_index (const_char_ptr, values, j++); + struct info_probe_column column = headings[ix]; + const char *val = values[ix]; if (val == NULL) - current_uiout->field_skip (column->field_name); + current_uiout->field_skip (column.field_name); else - current_uiout->field_string (column->field_name, val); + current_uiout->field_string (column.field_name, val); } - - do_cleanups (c); } /* Helper function that returns the number of extra fields which POPS will need. */ static int -get_number_extra_fields (const struct probe_ops *pops) +get_number_extra_fields (const static_probe_ops *spops) { - VEC (info_probe_column_s) *headings = NULL; - struct cleanup *c; - int n; - - if (pops->gen_info_probes_table_header == NULL) - return 0; - - c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings); - pops->gen_info_probes_table_header (&headings); - - n = VEC_length (info_probe_column_s, headings); - - do_cleanups (c); - - return n; + return spops->gen_info_probes_table_header ().size (); } -/* Helper function that returns 1 if there is a probe in PROBES - featuring the given POPS. It returns 0 otherwise. */ +/* Helper function that returns true if there is a probe in PROBES + featuring the given SPOPS. It returns false otherwise. */ -static int -exists_probe_with_pops (const std::vector &probes, - const struct probe_ops *pops) +static bool +exists_probe_with_spops (const std::vector &probes, + const static_probe_ops *spops) { - struct bound_probe *probe; - int ix; - for (const bound_probe &probe : probes) - if (probe.probe->pops == pops) - return 1; + if (probe.prob->get_static_ops () == spops) + return true; - return 0; + return false; } /* Helper function that parses a probe linespec of the form [PROVIDER @@ -538,8 +479,8 @@ parse_probe_linespec (const char *str, std::string *provider, /* See comment in probe.h. */ void -info_probes_for_ops (const char *arg, int from_tty, - const struct probe_ops *pops) +info_probes_for_spops (const char *arg, int from_tty, + const static_probe_ops *spops) { std::string provider, probe_name, objname; int any_found; @@ -554,26 +495,28 @@ info_probes_for_ops (const char *arg, int from_tty, parse_probe_linespec (arg, &provider, &probe_name, &objname); std::vector probes - = collect_probes (objname, provider, probe_name, pops); + = collect_probes (objname, provider, probe_name, spops); - if (pops == NULL) + if (spops == &any_static_probe_ops) { - /* If the probe_ops is NULL, it means the user has requested a "simple" - `info probes', i.e., she wants to print all information about all - probes. For that, we have to identify how many extra fields we will - need to add in the ui_out table. - - To do that, we iterate over all probe_ops, querying each one about - its extra fields, and incrementing `ui_out_extra_fields' to reflect - that number. But note that we ignore the probe_ops for which no probes - are defined with the given search criteria. */ - - for (const probe_ops *po : all_probe_ops) - if (exists_probe_with_pops (probes, po)) + /* If SPOPS is &any_static_probe_ops, it means the user has + requested a "simple" `info probes', i.e., she wants to print + all information about all probes. For that, we have to + identify how many extra fields we will need to add in the + ui_out table. + + To do that, we iterate over all static_probe_ops, querying + each one about its extra fields, and incrementing + `ui_out_extra_fields' to reflect that number. But note that + we ignore the static_probe_ops for which no probes are + defined with the given search criteria. */ + + for (const static_probe_ops *po : all_static_probe_ops) + if (exists_probe_with_spops (probes, po)) ui_out_extra_fields += get_number_extra_fields (po); } else - ui_out_extra_fields = get_number_extra_fields (pops); + ui_out_extra_fields = get_number_extra_fields (spops); { ui_out_emit_table table_emitter (current_uiout, @@ -589,11 +532,12 @@ info_probes_for_ops (const char *arg, int from_tty, `name' and `objname'). */ for (const bound_probe &probe : probes) { - const char *probe_type = probe.probe->pops->type_name (probe.probe); + const char *probe_type = probe.prob->get_static_ops ()->type_name (); size_type = std::max (strlen (probe_type), size_type); - size_name = std::max (strlen (probe.probe->name), size_name); - size_provider = std::max (strlen (probe.probe->provider), size_provider); + size_name = std::max (probe.prob->get_name ().size (), size_name); + size_provider = std::max (probe.prob->get_provider ().size (), + size_provider); size_objname = std::max (strlen (objfile_name (probe.objfile)), size_objname); } @@ -604,44 +548,46 @@ info_probes_for_ops (const char *arg, int from_tty, current_uiout->table_header (size_name, ui_left, "name", _("Name")); current_uiout->table_header (size_addr, ui_left, "addr", _("Where")); - if (pops == NULL) + if (spops == &any_static_probe_ops) { /* We have to generate the table header for each new probe type that we will print. Note that this excludes probe types not having any defined probe with the search criteria. */ - for (const probe_ops *po : all_probe_ops) - if (exists_probe_with_pops (probes, po)) + for (const static_probe_ops *po : all_static_probe_ops) + if (exists_probe_with_spops (probes, po)) gen_ui_out_table_header_info (probes, po); } else - gen_ui_out_table_header_info (probes, pops); + gen_ui_out_table_header_info (probes, spops); current_uiout->table_header (size_objname, ui_left, "object", _("Object")); current_uiout->table_body (); for (const bound_probe &probe : probes) { - const char *probe_type = probe.probe->pops->type_name (probe.probe); + const char *probe_type = probe.prob->get_static_ops ()->type_name (); ui_out_emit_tuple tuple_emitter (current_uiout, "probe"); - current_uiout->field_string ("type",probe_type); - current_uiout->field_string ("provider", probe.probe->provider); - current_uiout->field_string ("name", probe.probe->name); - current_uiout->field_core_addr ("addr", probe.probe->arch, - get_probe_address (probe.probe, - probe.objfile)); + current_uiout->field_string ("type", probe_type); + current_uiout->field_string ("provider", probe.prob->get_provider ()); + current_uiout->field_string ("name", probe.prob->get_name ()); + current_uiout->field_core_addr ("addr", probe.prob->get_gdbarch (), + probe.prob->get_relocated_address + (probe.objfile)); - if (pops == NULL) + if (spops == &any_static_probe_ops) { - for (const probe_ops *po : all_probe_ops) - if (probe.probe->pops == po) - print_ui_out_info (probe.probe); - else if (exists_probe_with_pops (probes, po)) - print_ui_out_not_applicables (po); + for (const static_probe_ops *po : all_static_probe_ops) + { + if (probe.prob->get_static_ops () == po) + print_ui_out_info (probe.prob); + else if (exists_probe_with_spops (probes, po)) + print_ui_out_not_applicables (po); + } } else - print_ui_out_info (probe.probe); + print_ui_out_info (probe.prob); current_uiout->field_string ("object", objfile_name (probe.objfile)); @@ -660,7 +606,7 @@ info_probes_for_ops (const char *arg, int from_tty, static void info_probes_command (const char *arg, int from_tty) { - info_probes_for_ops (arg, from_tty, NULL); + info_probes_for_spops (arg, from_tty, &any_static_probe_ops); } /* Implementation of the `enable probes' command. */ @@ -670,10 +616,10 @@ enable_probes_command (const char *arg, int from_tty) { std::string provider, probe_name, objname; - parse_probe_linespec ((const char *) arg, &provider, &probe_name, &objname); + parse_probe_linespec (arg, &provider, &probe_name, &objname); std::vector probes - = collect_probes (objname, provider, probe_name, NULL); + = collect_probes (objname, provider, probe_name, &any_static_probe_ops); if (probes.empty ()) { current_uiout->message (_("No probes matched.\n")); @@ -684,17 +630,17 @@ enable_probes_command (const char *arg, int from_tty) notion of enabling a probe. */ for (const bound_probe &probe: probes) { - const struct probe_ops *pops = probe.probe->pops; - - if (pops->enable_probe != NULL) + if (probe.prob->get_static_ops ()->can_enable ()) { - pops->enable_probe (probe.probe); + probe.prob->enable (); current_uiout->message (_("Probe %s:%s enabled.\n"), - probe.probe->provider, probe.probe->name); + probe.prob->get_provider ().c_str (), + probe.prob->get_name ().c_str ()); } else current_uiout->message (_("Probe %s:%s cannot be enabled.\n"), - probe.probe->provider, probe.probe->name); + probe.prob->get_provider ().c_str (), + probe.prob->get_name ().c_str ()); } } @@ -705,10 +651,10 @@ disable_probes_command (const char *arg, int from_tty) { std::string provider, probe_name, objname; - parse_probe_linespec ((const char *) arg, &provider, &probe_name, &objname); + parse_probe_linespec (arg, &provider, &probe_name, &objname); std::vector probes - = collect_probes (objname, provider, probe_name, NULL /* pops */); + = collect_probes (objname, provider, probe_name, &any_static_probe_ops); if (probes.empty ()) { current_uiout->message (_("No probes matched.\n")); @@ -719,78 +665,148 @@ disable_probes_command (const char *arg, int from_tty) notion of enabling a probe. */ for (const bound_probe &probe : probes) { - const struct probe_ops *pops = probe.probe->pops; - - if (pops->disable_probe != NULL) + if (probe.prob->get_static_ops ()->can_enable ()) { - pops->disable_probe (probe.probe); + probe.prob->disable (); current_uiout->message (_("Probe %s:%s disabled.\n"), - probe.probe->provider, probe.probe->name); + probe.prob->get_provider ().c_str (), + probe.prob->get_name ().c_str ()); } else current_uiout->message (_("Probe %s:%s cannot be disabled.\n"), - probe.probe->provider, probe.probe->name); + probe.prob->get_provider ().c_str (), + probe.prob->get_name ().c_str ()); } } +static bool ignore_probes_p = false; +static bool ignore_probes_idx = 0; +static bool ignore_probes_verbose_p; +static std::optional ignore_probes_prov_pat[2]; +static std::optional ignore_probes_name_pat[2]; +static std::optional ignore_probes_obj_pat[2]; + /* See comments in probe.h. */ -CORE_ADDR -get_probe_address (struct probe *probe, struct objfile *objfile) +bool +ignore_probe_p (const char *provider, const char *name, + const char *objfile_name, const char *type) { - return probe->pops->get_probe_address (probe, objfile); + if (!ignore_probes_p) + return false; + + std::optional &re_prov + = ignore_probes_prov_pat[ignore_probes_idx]; + std::optional &re_name + = ignore_probes_name_pat[ignore_probes_idx]; + std::optional &re_obj + = ignore_probes_obj_pat[ignore_probes_idx]; + + bool res + = ((!re_prov + || re_prov->exec (provider, 0, NULL, 0) == 0) + && (!re_name + || re_name->exec (name, 0, NULL, 0) == 0) + && (!re_obj + || re_obj->exec (objfile_name, 0, NULL, 0) == 0)); + + if (res && ignore_probes_verbose_p) + gdb_printf (gdb_stdlog, _("Ignoring %s probe %s %s in %s.\n"), + type, provider, name, objfile_name); + + return res; } -/* See comments in probe.h. */ +/* Implementation of the `maintenance ignore-probes' command. */ -unsigned -get_probe_argument_count (struct probe *probe, struct frame_info *frame) +static void +ignore_probes_command (const char *arg, int from_tty) { - return probe->pops->get_probe_argument_count (probe, frame); -} + std::string ignore_provider, ignore_probe_name, ignore_objname; -/* See comments in probe.h. */ + bool verbose_p = false; + if (arg != nullptr) + { + const char *idx = arg; + std::string s = extract_arg (&idx); -int -can_evaluate_probe_arguments (struct probe *probe) -{ - return probe->pops->can_evaluate_probe_arguments (probe); -} + if (strcmp (s.c_str (), "-reset") == 0) + { + if (*idx != '\0') + error (_("-reset: no arguments allowed")); -/* See comments in probe.h. */ + ignore_probes_p = false; + gdb_printf (gdb_stdout, _("ignore-probes filter has been reset\n")); + return; + } -struct value * -evaluate_probe_argument (struct probe *probe, unsigned n, - struct frame_info *frame) -{ - return probe->pops->evaluate_probe_argument (probe, n, frame); + if (strcmp (s.c_str (), "-verbose") == 0 + || strcmp (s.c_str (), "-v") == 0) + { + verbose_p = true; + arg = idx; + } + } + + parse_probe_linespec (arg, &ignore_provider, &ignore_probe_name, + &ignore_objname); + + /* Parse the regular expressions, making sure that the old regular + expressions are still valid if an exception is throw. */ + int new_ignore_probes_idx = 1 - ignore_probes_idx; + std::optional &re_prov + = ignore_probes_prov_pat[new_ignore_probes_idx]; + std::optional &re_name + = ignore_probes_name_pat[new_ignore_probes_idx]; + std::optional &re_obj + = ignore_probes_obj_pat[new_ignore_probes_idx]; + re_prov.reset (); + re_name.reset (); + re_obj.reset (); + if (!ignore_provider.empty ()) + re_prov.emplace (ignore_provider.c_str (), REG_NOSUB, + _("Invalid provider regexp")); + if (!ignore_probe_name.empty ()) + re_name.emplace (ignore_probe_name.c_str (), REG_NOSUB, + _("Invalid probe regexp")); + if (!ignore_objname.empty ()) + re_obj.emplace (ignore_objname.c_str (), REG_NOSUB, + _("Invalid object file regexp")); + ignore_probes_idx = new_ignore_probes_idx; + + ignore_probes_p = true; + ignore_probes_verbose_p = verbose_p; + gdb_printf (gdb_stdout, _("ignore-probes filter has been set to:\n")); + gdb_printf (gdb_stdout, _("PROVIDER: '%s'\n"), ignore_provider.c_str ()); + gdb_printf (gdb_stdout, _("PROBE_NAME: '%s'\n"), ignore_probe_name.c_str ()); + gdb_printf (gdb_stdout, _("OBJNAME: '%s'\n"), ignore_objname.c_str ()); } /* See comments in probe.h. */ struct value * -probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n) +probe_safe_evaluate_at_pc (const frame_info_ptr &frame, unsigned n) { struct bound_probe probe; unsigned n_args; probe = find_probe_by_pc (get_frame_pc (frame)); - if (!probe.probe) + if (!probe.prob) return NULL; - n_args = get_probe_argument_count (probe.probe, frame); + n_args = probe.prob->get_argument_count (get_frame_arch (frame)); if (n >= n_args) return NULL; - return evaluate_probe_argument (probe.probe, n, frame); + return probe.prob->evaluate_argument (n, frame); } /* See comment in probe.h. */ -const struct probe_ops * -probe_linespec_to_ops (const char **linespecp) +const struct static_probe_ops * +probe_linespec_to_static_ops (const char **linespecp) { - for (const probe_ops *ops : all_probe_ops) + for (const static_probe_ops *ops : all_static_probe_ops) if (ops->is_linespec (linespecp)) return ops; @@ -820,31 +836,40 @@ probe_is_linespec_by_keyword (const char **linespecp, const char *const *keyword return 0; } -/* Implementation of `is_linespec' method for `struct probe_ops'. */ +/* Implementation of `is_linespec' method. */ -static int -probe_any_is_linespec (const char **linespecp) +bool +any_static_probe_ops::is_linespec (const char **linespecp) const { static const char *const keywords[] = { "-p", "-probe", NULL }; return probe_is_linespec_by_keyword (linespecp, keywords); } -/* Dummy method used for `probe_ops_any'. */ +/* Implementation of 'get_probes' method. */ -static void -probe_any_get_probes (std::vector *probesp, struct objfile *objfile) +void +any_static_probe_ops::get_probes (std::vector> *probesp, + struct objfile *objfile) const { /* No probes can be provided by this dummy backend. */ } -/* Operations associated with a generic probe. */ +/* Implementation of the 'type_name' method. */ -const struct probe_ops probe_ops_any = +const char * +any_static_probe_ops::type_name () const { - probe_any_is_linespec, - probe_any_get_probes, -}; + return NULL; +} + +/* Implementation of the 'gen_info_probes_table_header' method. */ + +std::vector +any_static_probe_ops::gen_info_probes_table_header () const +{ + return std::vector (); +} /* See comments in probe.h. */ @@ -864,8 +889,7 @@ If you specify TYPE, there may be additional arguments needed by the\n\ subcommand.\n\ If you do not specify any argument, or specify `all', then the command\n\ will show information about all types of probes."), - &info_probes_cmdlist, "info probes ", - 0/*allow-unknown*/, &infolist); + &info_probes_cmdlist, 0/*allow-unknown*/, &infolist); return &info_probes_cmdlist; } @@ -879,21 +903,20 @@ static struct value * compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar, void *data) { - struct frame_info *frame = get_selected_frame (_("No frame selected")); + frame_info_ptr frame = get_selected_frame (_("No frame selected")); CORE_ADDR pc = get_frame_pc (frame); int sel = (int) (uintptr_t) data; struct bound_probe pc_probe; - const struct sym_probe_fns *pc_probe_fns; unsigned n_args; /* SEL == -1 means "_probe_argc". */ gdb_assert (sel >= -1); pc_probe = find_probe_by_pc (pc); - if (pc_probe.probe == NULL) + if (pc_probe.prob == NULL) error (_("No probe at PC %s"), core_addr_to_string (pc)); - n_args = get_probe_argument_count (pc_probe.probe, frame); + n_args = pc_probe.prob->get_argument_count (arch); if (sel == -1) return value_from_longest (builtin_type (arch)->builtin_int, n_args); @@ -901,7 +924,7 @@ compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar, error (_("Invalid probe argument %d -- probe has %u arguments available"), sel, n_args); - return evaluate_probe_argument (pc_probe.probe, sel, frame); + return pc_probe.prob->evaluate_argument (sel, frame); } /* This is called to compile one of the $_probe_arg* convenience @@ -914,18 +937,16 @@ compile_probe_arg (struct internalvar *ivar, struct agent_expr *expr, CORE_ADDR pc = expr->scope; int sel = (int) (uintptr_t) data; struct bound_probe pc_probe; - const struct sym_probe_fns *pc_probe_fns; int n_args; - struct frame_info *frame = get_selected_frame (NULL); /* SEL == -1 means "_probe_argc". */ gdb_assert (sel >= -1); pc_probe = find_probe_by_pc (pc); - if (pc_probe.probe == NULL) + if (pc_probe.prob == NULL) error (_("No probe at PC %s"), core_addr_to_string (pc)); - n_args = get_probe_argument_count (pc_probe.probe, frame); + n_args = pc_probe.prob->get_argument_count (expr->gdbarch); if (sel == -1) { @@ -940,23 +961,23 @@ compile_probe_arg (struct internalvar *ivar, struct agent_expr *expr, error (_("Invalid probe argument %d -- probe has %d arguments available"), sel, n_args); - pc_probe.probe->pops->compile_to_ax (pc_probe.probe, expr, value, sel); + pc_probe.prob->compile_to_ax (expr, value, sel); } static const struct internalvar_funcs probe_funcs = { compute_probe_arg, compile_probe_arg, - NULL }; -std::vector all_probe_ops; +std::vector all_static_probe_ops; +void _initialize_probe (); void -_initialize_probe (void) +_initialize_probe () { - all_probe_ops.push_back (&probe_ops_any); + all_static_probe_ops.push_back (&any_static_probe_ops); create_internalvar_type_lazy ("_probe_argc", &probe_funcs, (void *) (uintptr_t) -1); @@ -1012,4 +1033,16 @@ If you do not specify any argument then the command will disable\n\ all defined probes."), &disablelist); + add_cmd ("ignore-probes", class_maintenance, ignore_probes_command, _("\ +Ignore probes.\n\ +Usage: maintenance ignore-probes [-v|-verbose] [PROVIDER [NAME [OBJECT]]]\n\ + maintenance ignore-probes -reset\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.\n\ +If you do not specify any argument then the command will ignore\n\ +all defined probes. To reset the ignore-probes filter, use the -reset form.\n\ +Only supported for SystemTap probes."), + &maintenancelist); }