X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fprobe.c;h=56f93dad9b3e29f42bbec6d43af9c1c38cb19a28;hb=0f48b757071509040d800ff9f7c8726e5828bd1a;hp=3b0bd2839c482ee3f495ee77eb47f072cda5870b;hpb=ecd75fc8eed3bde86036141228074a20e55dcfc9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/probe.c b/gdb/probe.c index 3b0bd2839c..56f93dad9b 100644 --- a/gdb/probe.c +++ b/gdb/probe.c @@ -1,6 +1,6 @@ /* Generic static probe support for GDB. - Copyright (C) 2012-2014 Free Software Foundation, Inc. + Copyright (C) 2012-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -26,37 +26,105 @@ #include "symtab.h" #include "progspace.h" #include "filenames.h" -#include "exceptions.h" #include "linespec.h" #include "gdb_regex.h" #include "frame.h" #include "arch-utils.h" +#include "value.h" +#include "ax.h" +#include "ax-gdb.h" +#include "location.h" #include +typedef struct bound_probe bound_probe_s; +DEF_VEC_O (bound_probe_s); + +/* 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, + struct program_space *search_pspace, + const char *objfile_namestr, + const char *provider, + const char *name, + struct symtabs_and_lines *result) +{ + struct objfile *objfile; + + ALL_PSPACE_OBJFILES (search_pspace, objfile) + { + VEC (probe_p) *probes; + struct probe *probe; + int ix; + + if (!objfile->sf || !objfile->sf->sym_probe_fns) + continue; + + if (objfile_namestr + && FILENAME_CMP (objfile_name (objfile), objfile_namestr) != 0 + && FILENAME_CMP (lbasename (objfile_name (objfile)), + objfile_namestr) != 0) + continue; + + probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); + + for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) + { + struct symtab_and_line *sal; + + if (probe_ops != &probe_ops_any && probe->pops != probe_ops) + continue; + + if (provider && strcmp (probe->provider, provider) != 0) + continue; + + if (strcmp (probe->name, name) != 0) + continue; + + ++result->nelts; + result->sals = XRESIZEVEC (struct symtab_and_line, result->sals, + result->nelts); + sal = &result->sals[result->nelts - 1]; + + init_sal (sal); + + 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; + } + } +} + /* See definition in probe.h. */ struct symtabs_and_lines -parse_probes (char **argptr, struct linespec_result *canonical) +parse_probes (const struct event_location *location, + struct program_space *search_pspace, + struct linespec_result *canonical) { - char *arg_start, *arg_end, *arg; + char *arg_end, *arg; char *objfile_namestr = NULL, *provider = NULL, *name, *p; struct cleanup *cleanup; struct symtabs_and_lines result; - struct objfile *objfile; - struct program_space *pspace; const struct probe_ops *probe_ops; - const char *cs; + const char *arg_start, *cs; result.sals = NULL; result.nelts = 0; - arg_start = *argptr; + gdb_assert (event_location_type (location) == PROBE_LOCATION); + arg_start = get_probe_location (location); - cs = *argptr; + cs = arg_start; probe_ops = probe_linespec_to_ops (&cs); - gdb_assert (probe_ops != NULL); + if (probe_ops == NULL) + error (_("'%s' is not a probe linespec"), arg_start); arg = (char *) cs; arg = skip_spaces (arg); @@ -105,52 +173,19 @@ parse_probes (char **argptr, struct linespec_result *canonical) if (objfile_namestr && *objfile_namestr == '\0') error (_("invalid objfile name")); - ALL_PSPACES (pspace) - ALL_PSPACE_OBJFILES (pspace, objfile) - { - VEC (probe_p) *probes; - struct probe *probe; - int ix; - - if (!objfile->sf || !objfile->sf->sym_probe_fns) - continue; - - if (objfile_namestr - && FILENAME_CMP (objfile_name (objfile), objfile_namestr) != 0 - && FILENAME_CMP (lbasename (objfile_name (objfile)), - objfile_namestr) != 0) - continue; - - probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); - - for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) - { - struct symtab_and_line *sal; - - if (probe_ops != &probe_ops_any && probe->pops != probe_ops) - continue; - - if (provider && strcmp (probe->provider, provider) != 0) - continue; - - if (strcmp (probe->name, name) != 0) - continue; - - ++result.nelts; - result.sals = xrealloc (result.sals, - result.nelts - * sizeof (struct symtab_and_line)); - sal = &result.sals[result.nelts - 1]; - - init_sal (sal); + if (search_pspace != NULL) + { + parse_probes_in_pspace (probe_ops, search_pspace, objfile_namestr, + provider, name, &result); + } + else + { + struct program_space *pspace; - sal->pc = probe->address; - sal->explicit_pc = 1; - sal->section = find_pc_overlay (sal->pc); - sal->pspace = pspace; - sal->probe = probe; - } - } + ALL_PSPACES (pspace) + parse_probes_in_pspace (probe_ops, pspace, objfile_namestr, + provider, name, &result); + } if (result.nelts == 0) { @@ -163,12 +198,15 @@ parse_probes (char **argptr, struct linespec_result *canonical) if (canonical) { + char *canon; + + canon = savestring (arg_start, arg_end - arg_start); + make_cleanup (xfree, canon); canonical->special_display = 1; canonical->pre_expanded = 1; - canonical->addr_string = savestring (*argptr, arg_end - *argptr); + canonical->location = new_probe_location (canon); } - *argptr = arg_end; do_cleanups (cleanup); return result; @@ -204,10 +242,14 @@ find_probes_in_objfile (struct objfile *objfile, const char *provider, /* See definition in probe.h. */ -struct probe * +struct bound_probe find_probe_by_pc (CORE_ADDR pc) { struct objfile *objfile; + struct bound_probe result; + + result.objfile = NULL; + result.probe = NULL; ALL_OBJFILES (objfile) { @@ -215,17 +257,22 @@ find_probe_by_pc (CORE_ADDR pc) int ix; struct probe *probe; - if (!objfile->sf || !objfile->sf->sym_probe_fns) + 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 (probe->address == pc) - return probe; + if (get_probe_address (probe, objfile) == pc) + { + result.objfile = objfile; + result.probe = probe; + return result; + } } - return NULL; + return result; } @@ -234,16 +281,16 @@ find_probe_by_pc (CORE_ADDR pc) If POPS is not NULL, only probes of this certain probe_ops will match. Each argument is a regexp, or NULL, which matches anything. */ -static VEC (probe_p) * +static VEC (bound_probe_s) * collect_probes (char *objname, char *provider, char *probe_name, const struct probe_ops *pops) { struct objfile *objfile; - VEC (probe_p) *result = NULL; + VEC (bound_probe_s) *result = NULL; struct cleanup *cleanup, *cleanup_temps; regex_t obj_pat, prov_pat, probe_pat; - cleanup = make_cleanup (VEC_cleanup (probe_p), &result); + cleanup = make_cleanup (VEC_cleanup (bound_probe_s), &result); cleanup_temps = make_cleanup (null_cleanup, NULL); if (provider != NULL) @@ -272,6 +319,8 @@ collect_probes (char *objname, char *provider, char *probe_name, for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) { + struct bound_probe bound; + if (pops != NULL && probe->pops != pops) continue; @@ -283,7 +332,9 @@ collect_probes (char *objname, char *provider, char *probe_name, && regexec (&probe_pat, probe->name, 0, NULL, 0) != 0) continue; - VEC_safe_push (probe_p, result, probe); + bound.objfile = objfile; + bound.probe = probe; + VEC_safe_push (bound_probe_s, result, &bound); } } @@ -292,26 +343,26 @@ collect_probes (char *objname, char *provider, char *probe_name, return result; } -/* A qsort comparison function for probe_p objects. */ +/* A qsort comparison function for bound_probe_s objects. */ static int compare_probes (const void *a, const void *b) { - const struct probe *pa = *((const struct probe **) a); - const struct probe *pb = *((const struct 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->provider, pb->provider); + v = strcmp (pa->probe->provider, pb->probe->provider); if (v) return v; - v = strcmp (pa->name, pb->name); + v = strcmp (pa->probe->name, pb->probe->name); if (v) return v; - if (pa->address < pb->address) + if (pa->probe->address < pb->probe->address) return -1; - if (pa->address > pb->address) + if (pa->probe->address > pb->probe->address) return 1; return strcmp (objfile_name (pa->objfile), objfile_name (pb->objfile)); @@ -321,7 +372,7 @@ compare_probes (const void *a, const void *b) crafted by `info_probes_for_ops'. */ static void -gen_ui_out_table_header_info (VEC (probe_p) *probes, +gen_ui_out_table_header_info (VEC (bound_probe_s) *probes, const struct probe_ops *p) { /* `headings' refers to the names of the columns when printing `info @@ -350,11 +401,11 @@ gen_ui_out_table_header_info (VEC (probe_p) *probes, VEC_iterate (info_probe_column_s, headings, ix, column); ++ix) { - struct probe *probe; + struct bound_probe *probe; int jx; size_t size_max = strlen (column->print_name); - for (jx = 0; VEC_iterate (probe_p, probes, jx, probe); ++jx) + for (jx = 0; VEC_iterate (bound_probe_s, probes, jx, probe); ++jx) { /* `probe_fields' refers to the values of each new field that this probe will display. */ @@ -363,11 +414,11 @@ gen_ui_out_table_header_info (VEC (probe_p) *probes, const char *val; int kx; - if (probe->pops != p) + if (probe->probe->pops != p) continue; c2 = make_cleanup (VEC_cleanup (const_char_ptr), &probe_fields); - p->gen_info_probes_table_values (probe, &probe_fields); + p->gen_info_probes_table_values (probe->probe, &probe_fields); gdb_assert (VEC_length (const_char_ptr, probe_fields) == headings_size); @@ -393,6 +444,31 @@ gen_ui_out_table_header_info (VEC (probe_p) *probes, do_cleanups (c); } +/* Helper function to print not-applicable strings for all the extra + columns defined in a probe_ops. */ + +static void +print_ui_out_not_applicables (const struct probe_ops *pops) +{ + 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) + ui_out_field_string (current_uiout, column->field_name, _("n/a")); + + do_cleanups (c); +} + /* Helper function to print extra information about a probe and an objfile represented by PROBE. */ @@ -465,39 +541,67 @@ get_number_extra_fields (const struct probe_ops *pops) return n; } +/* Helper function that returns 1 if there is a probe in PROBES + featuring the given POPS. It returns 0 otherwise. */ + +static int +exists_probe_with_pops (VEC (bound_probe_s) *probes, + const struct probe_ops *pops) +{ + 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; + + return 0; +} + +/* 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) +{ + *probe_name = *objname = NULL; + + *provider = extract_arg_const (&str); + if (*provider != NULL) + { + *probe_name = extract_arg_const (&str); + if (*probe_name != NULL) + *objname = extract_arg_const (&str); + } +} + /* See comment in probe.h. */ void -info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) +info_probes_for_ops (const char *arg, int from_tty, + const struct probe_ops *pops) { char *provider, *probe_name = NULL, *objname = NULL; struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); - VEC (probe_p) *probes; + VEC (bound_probe_s) *probes; int i, 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"); - struct probe *probe; + size_t size_type = strlen ("Type"); + struct bound_probe *probe; struct gdbarch *gdbarch = get_current_arch (); - /* Do we have a `provider:probe:objfile' style of linespec? */ - provider = extract_arg (&arg); - if (provider) - { - make_cleanup (xfree, provider); - - probe_name = extract_arg (&arg); - if (probe_name) - { - make_cleanup (xfree, probe_name); + parse_probe_linespec (arg, &provider, &probe_name, &objname); + make_cleanup (xfree, provider); + make_cleanup (xfree, probe_name); + make_cleanup (xfree, objname); - objname = extract_arg (&arg); - if (objname) - make_cleanup (xfree, objname); - } - } + probes = collect_probes (objname, provider, probe_name, pops); + make_cleanup (VEC_cleanup (probe_p), &probes); if (pops == NULL) { @@ -511,37 +615,42 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) 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. */ + 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) - ui_out_extra_fields += get_number_extra_fields (po); + if (exists_probe_with_pops (probes, po)) + ui_out_extra_fields += get_number_extra_fields (po); } else ui_out_extra_fields = get_number_extra_fields (pops); - probes = collect_probes (objname, provider, probe_name, pops); - make_cleanup (VEC_cleanup (probe_p), &probes); make_cleanup_ui_out_table_begin_end (current_uiout, - 4 + ui_out_extra_fields, - VEC_length (probe_p, probes), + 5 + ui_out_extra_fields, + VEC_length (bound_probe_s, probes), "StaticProbes"); - if (!VEC_empty (probe_p, probes)) - qsort (VEC_address (probe_p, probes), VEC_length (probe_p, probes), - sizeof (probe_p), compare_probes); + 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 (`provider', `name' and - `objname'). */ - for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i) + /* Determining the maximum size of each field (`type', `provider', + `name' and `objname'). */ + for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i) { - size_name = max (strlen (probe->name), size_name); - size_provider = max (strlen (probe->provider), size_provider); + const char *probe_type = probe->probe->pops->type_name (probe->probe); + + size_type = max (strlen (probe_type), size_type); + size_name = max (strlen (probe->probe->name), size_name); + size_provider = max (strlen (probe->probe->provider), size_provider); size_objname = max (strlen (objfile_name (probe->objfile)), size_objname); } + ui_out_table_header (current_uiout, size_type, ui_left, "type", _("Type")); ui_out_table_header (current_uiout, size_provider, ui_left, "provider", _("Provider")); ui_out_table_header (current_uiout, size_name, ui_left, "name", _("Name")); @@ -552,10 +661,12 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) const struct probe_ops *po; int ix; - /* We have to generate the table header for each new probe type that we - will print. */ + /* 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) - gen_ui_out_table_header_info (probes, po); + if (exists_probe_with_pops (probes, po)) + gen_ui_out_table_header_info (probes, po); } else gen_ui_out_table_header_info (probes, pops); @@ -564,17 +675,19 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) _("Object")); ui_out_table_body (current_uiout); - for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i) + 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"); - ui_out_field_string (current_uiout, "provider", probe->provider); - ui_out_field_string (current_uiout, "name", probe->name); + ui_out_field_string (current_uiout, "type",probe_type); + ui_out_field_string (current_uiout, "provider", probe->probe->provider); + ui_out_field_string (current_uiout, "name", probe->probe->name); ui_out_field_core_addr (current_uiout, "addr", - get_objfile_arch (probe->objfile), - probe->address); + probe->probe->arch, + get_probe_address (probe->probe, probe->objfile)); if (pops == NULL) { @@ -583,11 +696,13 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix) - if (probe->pops == po) - print_ui_out_info (probe); + 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); + print_ui_out_info (probe->probe); ui_out_field_string (current_uiout, "object", objfile_name (probe->objfile)); @@ -596,7 +711,7 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) do_cleanups (inner); } - any_found = !VEC_empty (probe_p, probes); + any_found = !VEC_empty (bound_probe_s, probes); do_cleanups (cleanup); if (!any_found) @@ -611,6 +726,106 @@ info_probes_command (char *arg, int from_tty) info_probes_for_ops (arg, from_tty, NULL); } +/* Implementation of the `enable probes' command. */ + +static void +enable_probes_command (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; + + 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)) + { + ui_out_message (current_uiout, 0, _("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) + { + const struct probe_ops *pops = probe->probe->pops; + + if (pops->enable_probe != NULL) + { + pops->enable_probe (probe->probe); + ui_out_message (current_uiout, 0, + _("Probe %s:%s enabled.\n"), + probe->probe->provider, probe->probe->name); + } + else + ui_out_message (current_uiout, 0, + _("Probe %s:%s cannot be enabled.\n"), + probe->probe->provider, probe->probe->name); + } + + do_cleanups (cleanup); +} + +/* Implementation of the `disable probes' command. */ + +static void +disable_probes_command (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; + + 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)) + { + ui_out_message (current_uiout, 0, _("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) + { + const struct probe_ops *pops = probe->probe->pops; + + if (pops->disable_probe != NULL) + { + pops->disable_probe (probe->probe); + ui_out_message (current_uiout, 0, + _("Probe %s:%s disabled.\n"), + probe->probe->provider, probe->probe->name); + } + else + ui_out_message (current_uiout, 0, + _("Probe %s:%s cannot be disabled.\n"), + probe->probe->provider, probe->probe->name); + } + + 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 @@ -641,18 +856,18 @@ evaluate_probe_argument (struct probe *probe, unsigned n, struct value * probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n) { - struct probe *probe; + struct bound_probe probe; unsigned n_args; probe = find_probe_by_pc (get_frame_pc (frame)); - if (!probe) + if (!probe.probe) return NULL; - n_args = get_probe_argument_count (probe, frame); + n_args = get_probe_argument_count (probe.probe, frame); if (n >= n_args) return NULL; - return evaluate_probe_argument (probe, n, frame); + return evaluate_probe_argument (probe.probe, n, frame); } /* See comment in probe.h. */ @@ -743,6 +958,87 @@ will show information about all types of probes."), return &info_probes_cmdlist; } + + +/* This is called to compute the value of one of the $_probe_arg* + convenience variables. */ + +static struct value * +compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar, + void *data) +{ + struct frame_info *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) + error (_("No probe at PC %s"), core_addr_to_string (pc)); + + n_args = get_probe_argument_count (pc_probe.probe, frame); + if (sel == -1) + return value_from_longest (builtin_type (arch)->builtin_int, n_args); + + if (sel >= n_args) + error (_("Invalid probe argument %d -- probe has %u arguments available"), + sel, n_args); + + return evaluate_probe_argument (pc_probe.probe, sel, frame); +} + +/* This is called to compile one of the $_probe_arg* convenience + variables into an agent expression. */ + +static void +compile_probe_arg (struct internalvar *ivar, struct agent_expr *expr, + struct axs_value *value, void *data) +{ + 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) + error (_("No probe at PC %s"), core_addr_to_string (pc)); + + n_args = get_probe_argument_count (pc_probe.probe, frame); + + if (sel == -1) + { + value->kind = axs_rvalue; + value->type = builtin_type (expr->gdbarch)->builtin_int; + ax_const_l (expr, n_args); + return; + } + + gdb_assert (sel >= 0); + if (sel >= n_args) + 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); +} + +static const struct internalvar_funcs probe_funcs = +{ + compute_probe_arg, + compile_probe_arg, + NULL +}; + + VEC (probe_ops_cp) *all_probe_ops; void _initialize_probe (void); @@ -752,8 +1048,58 @@ _initialize_probe (void) { VEC_safe_push (probe_ops_cp, all_probe_ops, &probe_ops_any); + create_internalvar_type_lazy ("_probe_argc", &probe_funcs, + (void *) (uintptr_t) -1); + create_internalvar_type_lazy ("_probe_arg0", &probe_funcs, + (void *) (uintptr_t) 0); + create_internalvar_type_lazy ("_probe_arg1", &probe_funcs, + (void *) (uintptr_t) 1); + create_internalvar_type_lazy ("_probe_arg2", &probe_funcs, + (void *) (uintptr_t) 2); + create_internalvar_type_lazy ("_probe_arg3", &probe_funcs, + (void *) (uintptr_t) 3); + create_internalvar_type_lazy ("_probe_arg4", &probe_funcs, + (void *) (uintptr_t) 4); + create_internalvar_type_lazy ("_probe_arg5", &probe_funcs, + (void *) (uintptr_t) 5); + create_internalvar_type_lazy ("_probe_arg6", &probe_funcs, + (void *) (uintptr_t) 6); + create_internalvar_type_lazy ("_probe_arg7", &probe_funcs, + (void *) (uintptr_t) 7); + create_internalvar_type_lazy ("_probe_arg8", &probe_funcs, + (void *) (uintptr_t) 8); + create_internalvar_type_lazy ("_probe_arg9", &probe_funcs, + (void *) (uintptr_t) 9); + create_internalvar_type_lazy ("_probe_arg10", &probe_funcs, + (void *) (uintptr_t) 10); + create_internalvar_type_lazy ("_probe_arg11", &probe_funcs, + (void *) (uintptr_t) 11); + add_cmd ("all", class_info, info_probes_command, _("\ Show information about all type of probes."), info_probes_cmdlist_get ()); + + add_cmd ("probes", class_breakpoint, enable_probes_command, _("\ +Enable probes.\n\ +Usage: enable probes [PROVIDER [NAME [OBJECT]]]\n\ +Each argument is a regular expression, used to select probes.\n\ +PROVIDER matches probe provider names.\n\ +NAME matches the probe names.\n\ +OBJECT matches the executable or shared library name.\n\ +If you do not specify any argument then the command will enable\n\ +all defined probes."), + &enablelist); + + add_cmd ("probes", class_breakpoint, disable_probes_command, _("\ +Disable probes.\n\ +Usage: disable probes [PROVIDER [NAME [OBJECT]]]\n\ +Each argument is a regular expression, used to select probes.\n\ +PROVIDER matches probe provider names.\n\ +NAME matches the probe names.\n\ +OBJECT matches the executable or shared library name.\n\ +If you do not specify any argument then the command will disable\n\ +all defined probes."), + &disablelist); + }