X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fprobe.c;h=8b108d6b02dce8e8dc87a7a01244199b740e93e6;hb=228c8f4be0c428369ec6b68e25696863d1e62ed7;hp=c147810354ede3f384462478d41ef71a4fbb6f52;hpb=8e9e35b1808481735e2d1efbf70ed7396a845d8e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/probe.c b/gdb/probe.c index c147810354..8b108d6b02 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-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -36,31 +36,45 @@ #include "location.h" #include #include +#include "gdbsupport/gdb_optional.h" -typedef struct bound_probe bound_probe_s; -DEF_VEC_O (bound_probe_s); +/* 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, - struct symtabs_and_lines *result) + std::vector *result) { - struct objfile *objfile; - - ALL_PSPACE_OBJFILES (search_pspace, objfile) + for (objfile *objfile : search_pspace->objfiles ()) { - VEC (probe_p) *probes; - struct probe *probe; - int ix; - if (!objfile->sf || !objfile->sf->sym_probe_fns) continue; @@ -70,61 +84,50 @@ parse_probes_in_pspace (const struct probe_ops *probe_ops, objfile_namestr) != 0) continue; - probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); + const std::vector> &probes + = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) + for (auto &p : probes) { - struct symtab_and_line *sal; - - if (probe_ops != &probe_ops_any && probe->pops != probe_ops) + if (spops != &any_static_probe_ops && p->get_static_ops () != spops) continue; - if (provider && strcmp (probe->provider, provider) != 0) + if (provider != NULL && p->get_provider () != provider) continue; - if (strcmp (probe->name, name) != 0) + if (p->get_name () != name) continue; - ++result->nelts; - result->sals = XRESIZEVEC (struct symtab_and_line, result->sals, - result->nelts); - sal = &result->sals[result->nelts - 1]; - - init_sal (sal); + symtab_and_line sal; + sal.pc = p->get_relocated_address (objfile); + sal.explicit_pc = 1; + sal.section = find_pc_overlay (sal.pc); + sal.pspace = search_pspace; + sal.prob = p.get (); + sal.objfile = objfile; - sal->pc = get_probe_address (probe, objfile); - sal->explicit_pc = 1; - sal->section = find_pc_overlay (sal->pc); - sal->pspace = search_pspace; - sal->probe = probe; - sal->objfile = objfile; + result->push_back (std::move (sal)); } } } /* See definition in probe.h. */ -struct symtabs_and_lines +std::vector parse_probes (const struct event_location *location, struct program_space *search_pspace, struct linespec_result *canonical) { char *arg_end, *arg; char *objfile_namestr = NULL, *provider = NULL, *name, *p; - struct cleanup *cleanup; - struct symtabs_and_lines result; - const struct probe_ops *probe_ops; const char *arg_start, *cs; - result.sals = NULL; - result.nelts = 0; - gdb_assert (event_location_type (location) == PROBE_LOCATION); arg_start = get_probe_location (location); 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; @@ -135,8 +138,8 @@ parse_probes (const struct event_location *location, arg_end = skip_to_space (arg); /* We make a copy here so we can write over parts with impunity. */ - arg = savestring (arg, arg_end - arg); - cleanup = make_cleanup (xfree, arg); + std::string copy (arg, arg_end - arg); + arg = ©[0]; /* Extract each word from the argument, separated by ":"s. */ p = strchr (arg, ':'); @@ -174,9 +177,10 @@ parse_probes (const struct event_location *location, if (objfile_namestr && *objfile_namestr == '\0') error (_("invalid objfile name")); + 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 @@ -184,11 +188,11 @@ parse_probes (const struct event_location *location, struct program_space *pspace; ALL_PSPACES (pspace) - parse_probes_in_pspace (probe_ops, pspace, objfile_namestr, + parse_probes_in_pspace (spops, pspace, objfile_namestr, provider, name, &result); } - if (result.nelts == 0) + if (result.empty ()) { throw_error (NOT_FOUND_ERROR, _("No probe matching objfile=`%s', provider=`%s', name=`%s'"), @@ -199,43 +203,37 @@ parse_probes (const struct event_location *location, if (canonical) { - char *canon; - - canon = savestring (arg_start, arg_end - arg_start); - make_cleanup (xfree, canon); + std::string canon (arg_start, arg_end - arg_start); canonical->special_display = 1; canonical->pre_expanded = 1; - canonical->location = new_probe_location (canon); + canonical->location = new_probe_location (canon.c_str ()); } - do_cleanups (cleanup); - return result; } /* 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) *probes, *result = NULL; - int ix; - struct probe *probe; + std::vector result; if (!objfile->sf || !objfile->sf->sym_probe_fns) - return NULL; + return result; - probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) + const std::vector> &probes + = objfile->sf->sym_probe_fns->sym_get_probes (objfile); + for (auto &p : probes) { - if (strcmp (probe->provider, provider) != 0) + if (p->get_provider () != provider) continue; - if (strcmp (probe->name, name) != 0) + if (p->get_name () != name) continue; - VEC_safe_push (probe_p, result, probe); + result.push_back (p.get ()); } return result; @@ -246,32 +244,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) - { - VEC (probe_p) *probes; - int ix; - struct probe *probe; - - 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. */ - probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) - if (get_probe_address (probe, objfile) == pc) - { - result.objfile = objfile; - result.probe = probe; - 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; } @@ -279,153 +273,114 @@ 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 VEC (bound_probe_s) * -collect_probes (char *objname, char *provider, char *probe_name, - const struct probe_ops *pops) +static std::vector +collect_probes (const std::string &objname, const std::string &provider, + const std::string &probe_name, const static_probe_ops *spops) { - struct objfile *objfile; - VEC (bound_probe_s) *result = NULL; - struct cleanup *cleanup, *cleanup_temps; - regex_t obj_pat, prov_pat, probe_pat; - - cleanup = make_cleanup (VEC_cleanup (bound_probe_s), &result); - - cleanup_temps = make_cleanup (null_cleanup, NULL); - if (provider != NULL) - compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp")); - if (probe_name != NULL) - compile_rx_or_error (&probe_pat, probe_name, _("Invalid probe regexp")); - if (objname != NULL) - compile_rx_or_error (&obj_pat, objname, _("Invalid object file regexp")); - - ALL_OBJFILES (objfile) + std::vector result; + gdb::optional obj_pat, prov_pat, probe_pat; + + if (!provider.empty ()) + prov_pat.emplace (provider.c_str (), REG_NOSUB, + _("Invalid provider regexp")); + if (!probe_name.empty ()) + probe_pat.emplace (probe_name.c_str (), REG_NOSUB, + _("Invalid probe regexp")); + if (!objname.empty ()) + obj_pat.emplace (objname.c_str (), REG_NOSUB, + _("Invalid object file regexp")); + + for (objfile *objfile : current_program_space->objfiles ()) { - VEC (probe_p) *probes; - struct probe *probe; - int ix; - if (! objfile->sf || ! objfile->sf->sym_probe_fns) continue; - if (objname) + if (obj_pat) { - if (regexec (&obj_pat, objfile_name (objfile), 0, NULL, 0) != 0) + if (obj_pat->exec (objfile_name (objfile), 0, NULL, 0) != 0) continue; } - probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); + const std::vector> &probes + = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) + for (auto &p : probes) { - struct bound_probe bound; - - if (pops != NULL && probe->pops != pops) + if (spops != &any_static_probe_ops && p->get_static_ops () != spops) continue; - if (provider - && regexec (&prov_pat, probe->provider, 0, NULL, 0) != 0) + if (prov_pat + && prov_pat->exec (p->get_provider ().c_str (), 0, NULL, 0) != 0) continue; - if (probe_name - && regexec (&probe_pat, probe->name, 0, NULL, 0) != 0) + if (probe_pat + && probe_pat->exec (p->get_name ().c_str (), 0, NULL, 0) != 0) continue; - bound.objfile = objfile; - bound.probe = probe; - VEC_safe_push (bound_probe_s, result, &bound); + result.emplace_back (p.get (), objfile); } } - do_cleanups (cleanup_temps); - discard_cleanups (cleanup); return result; } /* A qsort comparison function for bound_probe_s objects. */ -static int -compare_probes (const void *a, const void *b) +static bool +compare_probes (const bound_probe &a, const bound_probe &b) { - const struct bound_probe *pa = (const struct bound_probe *) a; - const struct bound_probe *pb = (const struct bound_probe *) b; int v; - v = strcmp (pa->probe->provider, pb->probe->provider); - if (v) - return v; + v = a.prob->get_provider ().compare (b.prob->get_provider ()); + if (v != 0) + return v < 0; - v = strcmp (pa->probe->name, pb->probe->name); - if (v) - return v; + v = a.prob->get_name ().compare (b.prob->get_name ()); + if (v != 0) + return v < 0; - if (pa->probe->address < pb->probe->address) - return -1; - if (pa->probe->address > pb->probe->address) - return 1; + if (a.prob->get_address () != b.prob->get_address ()) + return a.prob->get_address () < b.prob->get_address (); - return strcmp (objfile_name (pa->objfile), objfile_name (pb->objfile)); + return strcmp (objfile_name (a.objfile), objfile_name (b.objfile)) < 0; } /* Helper function that generate entries in the ui_out table being crafted by `info_probes_for_ops'. */ static void -gen_ui_out_table_header_info (VEC (bound_probe_s) *probes, - const struct probe_ops *p) +gen_ui_out_table_header_info (const std::vector &probes, + 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 (spops != NULL); - gdb_assert (p->gen_info_probes_table_header != NULL - && p->gen_info_probes_table_values != NULL); + std::vector headings + = spops->gen_info_probes_table_header (); - c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings); - p->gen_info_probes_table_header (&headings); - - 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) { - struct bound_probe *probe; - int jx; - size_t size_max = strlen (column->print_name); + size_t size_max = strlen (column.print_name); - for (jx = 0; VEC_iterate (bound_probe_s, probes, jx, probe); ++jx) + 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 @@ -435,285 +390,216 @@ gen_ui_out_table_header_info (VEC (bound_probe_s) *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; + std::vector headings + = spops->gen_info_probes_table_header (); - 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")); - - 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; + std::vector headings + = probe->get_static_ops ()->gen_info_probes_table_header (); + std::vector values + = probe->gen_info_probes_table_values (); - gdb_assert (probe->pops->gen_info_probes_table_header != NULL - && probe->pops->gen_info_probes_table_values != NULL); + gdb_assert (headings.size () == values.size ()); - 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); - - gdb_assert (VEC_length (info_probe_column_s, headings) - == VEC_length (const_char_ptr, values)); - - 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 (VEC (bound_probe_s) *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 (ix = 0; VEC_iterate (bound_probe_s, probes, ix, probe); ++ix) - if (probe->probe->pops == pops) - return 1; + for (const bound_probe &probe : probes) + if (probe.prob->get_static_ops () == spops) + return true; - return 0; + return false; } /* Helper function that parses a probe linespec of the form [PROVIDER [PROBE [OBJNAME]]] from the provided string STR. */ static void -parse_probe_linespec (const char *str, char **provider, - char **probe_name, char **objname) +parse_probe_linespec (const char *str, std::string *provider, + std::string *probe_name, std::string *objname) { - *probe_name = *objname = NULL; + *probe_name = *objname = ""; - *provider = extract_arg_const (&str); - if (*provider != NULL) + *provider = extract_arg (&str); + if (!provider->empty ()) { - *probe_name = extract_arg_const (&str); - if (*probe_name != NULL) - *objname = extract_arg_const (&str); + *probe_name = extract_arg (&str); + if (!probe_name->empty ()) + *objname = extract_arg (&str); } } /* 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) { - char *provider, *probe_name = NULL, *objname = NULL; - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); - VEC (bound_probe_s) *probes; - int i, any_found; + std::string provider, probe_name, objname; + int any_found; int ui_out_extra_fields = 0; size_t size_addr; size_t size_name = strlen ("Name"); size_t size_objname = strlen ("Object"); size_t size_provider = strlen ("Provider"); size_t size_type = strlen ("Type"); - struct bound_probe *probe; struct gdbarch *gdbarch = get_current_arch (); parse_probe_linespec (arg, &provider, &probe_name, &objname); - make_cleanup (xfree, provider); - make_cleanup (xfree, probe_name); - make_cleanup (xfree, objname); - probes = collect_probes (objname, provider, probe_name, pops); - make_cleanup (VEC_cleanup (probe_p), &probes); + std::vector probes + = collect_probes (objname, provider, probe_name, spops); - if (pops == NULL) + if (spops == &any_static_probe_ops) { - const struct probe_ops *po; - int ix; - - /* 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 (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix) - 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); - - make_cleanup_ui_out_table_begin_end (current_uiout, - 5 + ui_out_extra_fields, - VEC_length (bound_probe_s, probes), - "StaticProbes"); - - if (!VEC_empty (bound_probe_s, probes)) - qsort (VEC_address (bound_probe_s, probes), - VEC_length (bound_probe_s, probes), - sizeof (bound_probe_s), compare_probes); - - /* What's the size of an address in our architecture? */ - size_addr = gdbarch_addr_bit (gdbarch) == 64 ? 18 : 10; - - /* Determining the maximum size of each field (`type', `provider', - `name' and `objname'). */ - for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i) - { - const char *probe_type = probe->probe->pops->type_name (probe->probe); - - 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_objname = std::max (strlen (objfile_name (probe->objfile)), - size_objname); - } - - current_uiout->table_header (size_type, ui_left, "type", _("Type")); - current_uiout->table_header (size_provider, ui_left, "provider", - _("Provider")); - current_uiout->table_header (size_name, ui_left, "name", _("Name")); - current_uiout->table_header (size_addr, ui_left, "addr", _("Where")); - - if (pops == NULL) - { - const struct probe_ops *po; - int ix; - - /* 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 (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix) - if (exists_probe_with_pops (probes, po)) - gen_ui_out_table_header_info (probes, po); - } - else - gen_ui_out_table_header_info (probes, pops); - - current_uiout->table_header (size_objname, ui_left, "object", _("Object")); - current_uiout->table_body (); - - for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i) - { - struct cleanup *inner; - const char *probe_type = probe->probe->pops->type_name (probe->probe); - - inner = make_cleanup_ui_out_tuple_begin_end (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)); - - if (pops == NULL) - { - const struct probe_ops *po; - int ix; - - for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); - ++ix) - 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); - } - else - print_ui_out_info (probe->probe); + ui_out_extra_fields = get_number_extra_fields (spops); - current_uiout->field_string ("object", - objfile_name (probe->objfile)); - current_uiout->text ("\n"); - - do_cleanups (inner); - } - - any_found = !VEC_empty (bound_probe_s, probes); - do_cleanups (cleanup); + { + ui_out_emit_table table_emitter (current_uiout, + 5 + ui_out_extra_fields, + probes.size (), "StaticProbes"); + + std::sort (probes.begin (), probes.end (), compare_probes); + + /* What's the size of an address in our architecture? */ + size_addr = gdbarch_addr_bit (gdbarch) == 64 ? 18 : 10; + + /* Determining the maximum size of each field (`type', `provider', + `name' and `objname'). */ + for (const bound_probe &probe : probes) + { + const char *probe_type = probe.prob->get_static_ops ()->type_name (); + + size_type = std::max (strlen (probe_type), size_type); + 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); + } + + current_uiout->table_header (size_type, ui_left, "type", _("Type")); + current_uiout->table_header (size_provider, ui_left, "provider", + _("Provider")); + current_uiout->table_header (size_name, ui_left, "name", _("Name")); + current_uiout->table_header (size_addr, ui_left, "addr", _("Where")); + + 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 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, 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.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.prob->get_provider ().c_str ()); + current_uiout->field_string ("name", probe.prob->get_name ().c_str ()); + current_uiout->field_core_addr ("addr", probe.prob->get_gdbarch (), + probe.prob->get_relocated_address + (probe.objfile)); + + if (spops == &any_static_probe_ops) + { + 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.prob); + + current_uiout->field_string ("object", + objfile_name (probe.objfile)); + current_uiout->text ("\n"); + } + + any_found = !probes.empty (); + } if (!any_found) current_uiout->message (_("No probes matched.\n")); @@ -722,130 +608,79 @@ info_probes_for_ops (const char *arg, int from_tty, /* Implementation of the `info probes' command. */ static void -info_probes_command (char *arg, int from_tty) +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. */ static void -enable_probes_command (char *arg, int from_tty) +enable_probes_command (const char *arg, int from_tty) { - char *provider, *probe_name = NULL, *objname = NULL; - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); - VEC (bound_probe_s) *probes; - struct bound_probe *probe; - int i; + std::string provider, probe_name, objname; parse_probe_linespec ((const char *) arg, &provider, &probe_name, &objname); - make_cleanup (xfree, provider); - make_cleanup (xfree, probe_name); - make_cleanup (xfree, objname); - probes = collect_probes (objname, provider, probe_name, NULL); - if (VEC_empty (bound_probe_s, probes)) + std::vector probes + = collect_probes (objname, provider, probe_name, &any_static_probe_ops); + if (probes.empty ()) { current_uiout->message (_("No probes matched.\n")); - do_cleanups (cleanup); return; } /* Enable the selected probes, provided their backends support the notion of enabling a probe. */ - for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i) + 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 ()); } - - do_cleanups (cleanup); } /* Implementation of the `disable probes' command. */ static void -disable_probes_command (char *arg, int from_tty) +disable_probes_command (const char *arg, int from_tty) { - char *provider, *probe_name = NULL, *objname = NULL; - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); - VEC (bound_probe_s) *probes; - struct bound_probe *probe; - int i; + std::string provider, probe_name, objname; parse_probe_linespec ((const char *) arg, &provider, &probe_name, &objname); - make_cleanup (xfree, provider); - make_cleanup (xfree, probe_name); - make_cleanup (xfree, objname); - probes = collect_probes (objname, provider, probe_name, NULL /* pops */); - if (VEC_empty (bound_probe_s, probes)) + std::vector probes + = collect_probes (objname, provider, probe_name, &any_static_probe_ops); + if (probes.empty ()) { current_uiout->message (_("No probes matched.\n")); - do_cleanups (cleanup); return; } /* Disable the selected probes, provided their backends support the notion of enabling a probe. */ - for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i) + 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 ()); } - - do_cleanups (cleanup); -} - -/* See comments in probe.h. */ - -CORE_ADDR -get_probe_address (struct probe *probe, struct objfile *objfile) -{ - return probe->pops->get_probe_address (probe, objfile); -} - -/* See comments in probe.h. */ - -unsigned -get_probe_argument_count (struct probe *probe, struct frame_info *frame) -{ - return probe->pops->get_probe_argument_count (probe, frame); -} - -/* See comments in probe.h. */ - -int -can_evaluate_probe_arguments (struct probe *probe) -{ - return probe->pops->can_evaluate_probe_arguments (probe); -} - -/* See comments in probe.h. */ - -struct value * -evaluate_probe_argument (struct probe *probe, unsigned n, - struct frame_info *frame) -{ - return probe->pops->evaluate_probe_argument (probe, n, frame); } /* See comments in probe.h. */ @@ -857,27 +692,24 @@ probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n) 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) { - int ix; - const struct probe_ops *probe_ops; - - for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, probe_ops); ix++) - if (probe_ops->is_linespec (linespecp)) - return probe_ops; + for (const static_probe_ops *ops : all_static_probe_ops) + if (ops->is_linespec (linespecp)) + return ops; return NULL; } @@ -905,31 +737,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 (VEC (probe_p) **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. */ @@ -968,17 +809,16 @@ compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar, 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); @@ -986,7 +826,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 @@ -999,18 +839,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) { @@ -1025,7 +863,7 @@ 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 = @@ -1036,14 +874,12 @@ static const struct internalvar_funcs probe_funcs = }; -VEC (probe_ops_cp) *all_probe_ops; - -void _initialize_probe (void); +std::vector all_static_probe_ops; void _initialize_probe (void) { - VEC_safe_push (probe_ops_cp, all_probe_ops, &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);