| Index: gdb/probe.c
|
| diff --git a/gdb/probe.c b/gdb/probe.c
|
| index 77f3b13478ad040eab036dbdf8da6e2426f87e4c..c1e0111529373fb38ab3f2ba2b66a3b0042a0137 100644
|
| --- a/gdb/probe.c
|
| +++ b/gdb/probe.c
|
| @@ -1,6 +1,6 @@
|
| /* Generic static probe support for GDB.
|
|
|
| - Copyright (C) 2012 Free Software Foundation, Inc.
|
| + Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -41,7 +41,7 @@ struct symtabs_and_lines
|
| parse_probes (char **argptr, struct linespec_result *canonical)
|
| {
|
| char *arg_start, *arg_end, *arg;
|
| - char *objfile_name = NULL, *provider = NULL, *name, *p;
|
| + char *objfile_namestr = NULL, *provider = NULL, *name, *p;
|
| struct cleanup *cleanup;
|
| struct symtabs_and_lines result;
|
| struct objfile *objfile;
|
| @@ -92,7 +92,7 @@ parse_probes (char **argptr, struct linespec_result *canonical)
|
| {
|
| /* This is `-p objfile:provider:name'. */
|
| *p = '\0';
|
| - objfile_name = arg;
|
| + objfile_namestr = arg;
|
| provider = hold;
|
| name = p + 1;
|
| }
|
| @@ -102,7 +102,7 @@ parse_probes (char **argptr, struct linespec_result *canonical)
|
| error (_("no probe name specified"));
|
| if (provider && *provider == '\0')
|
| error (_("invalid provider name"));
|
| - if (objfile_name && *objfile_name == '\0')
|
| + if (objfile_namestr && *objfile_namestr == '\0')
|
| error (_("invalid objfile name"));
|
|
|
| ALL_PSPACES (pspace)
|
| @@ -115,9 +115,10 @@ parse_probes (char **argptr, struct linespec_result *canonical)
|
| if (!objfile->sf || !objfile->sf->sym_probe_fns)
|
| continue;
|
|
|
| - if (objfile_name
|
| - && FILENAME_CMP (objfile->name, objfile_name) != 0
|
| - && FILENAME_CMP (lbasename (objfile->name), objfile_name) != 0)
|
| + 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);
|
| @@ -155,7 +156,7 @@ parse_probes (char **argptr, struct linespec_result *canonical)
|
| {
|
| throw_error (NOT_FOUND_ERROR,
|
| _("No probe matching objfile=`%s', provider=`%s', name=`%s'"),
|
| - objfile_name ? objfile_name : _("<any>"),
|
| + objfile_namestr ? objfile_namestr : _("<any>"),
|
| provider ? provider : _("<any>"),
|
| name);
|
| }
|
| @@ -204,7 +205,7 @@ find_probes_in_objfile (struct objfile *objfile, const char *provider,
|
| /* See definition in probe.h. */
|
|
|
| struct probe *
|
| -find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out)
|
| +find_probe_by_pc (CORE_ADDR pc)
|
| {
|
| struct objfile *objfile;
|
|
|
| @@ -221,10 +222,7 @@ find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out)
|
| 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)
|
| - {
|
| - *objfile_out = objfile;
|
| - return probe;
|
| - }
|
| + return probe;
|
| }
|
|
|
| return NULL;
|
| @@ -232,64 +230,28 @@ find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out)
|
|
|
|
|
|
|
| -/* A utility structure. A VEC of these is built when handling "info
|
| - probes". */
|
| -
|
| -struct probe_and_objfile
|
| -{
|
| - /* The probe. */
|
| - struct probe *probe;
|
| -
|
| - /* The probe's objfile. */
|
| - struct objfile *objfile;
|
| -};
|
| -
|
| -typedef struct probe_and_objfile probe_and_objfile_s;
|
| -DEF_VEC_O (probe_and_objfile_s);
|
| -
|
| -/* A helper function for collect_probes that compiles a regexp and
|
| - throws an exception on error. This installs a cleanup to free the
|
| - resulting pattern on success. If RX is NULL, this does nothing. */
|
| -
|
| -static void
|
| -compile_rx_or_error (regex_t *pattern, const char *rx, const char *message)
|
| -{
|
| - int code;
|
| -
|
| - if (!rx)
|
| - return;
|
| -
|
| - code = regcomp (pattern, rx, REG_NOSUB);
|
| - if (code == 0)
|
| - make_regfree_cleanup (pattern);
|
| - else
|
| - {
|
| - char *err = get_regcomp_error (code, pattern);
|
| -
|
| - make_cleanup (xfree, err);
|
| - error (("%s: %s"), message, err);
|
| - }
|
| -}
|
| -
|
| /* 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. */
|
|
|
| -static VEC (probe_and_objfile_s) *
|
| +static VEC (probe_p) *
|
| collect_probes (char *objname, char *provider, char *probe_name,
|
| const struct probe_ops *pops)
|
| {
|
| struct objfile *objfile;
|
| - VEC (probe_and_objfile_s) *result = NULL;
|
| + VEC (probe_p) *result = NULL;
|
| struct cleanup *cleanup, *cleanup_temps;
|
| regex_t obj_pat, prov_pat, probe_pat;
|
|
|
| - cleanup = make_cleanup (VEC_cleanup (probe_and_objfile_s), &result);
|
| + cleanup = make_cleanup (VEC_cleanup (probe_p), &result);
|
|
|
| cleanup_temps = make_cleanup (null_cleanup, NULL);
|
| - compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp"));
|
| - compile_rx_or_error (&probe_pat, probe_name, _("Invalid probe regexp"));
|
| - compile_rx_or_error (&obj_pat, objname, _("Invalid object file regexp"));
|
| + 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)
|
| {
|
| @@ -302,7 +264,7 @@ collect_probes (char *objname, char *provider, char *probe_name,
|
|
|
| if (objname)
|
| {
|
| - if (regexec (&obj_pat, objfile->name, 0, NULL, 0) != 0)
|
| + if (regexec (&obj_pat, objfile_name (objfile), 0, NULL, 0) != 0)
|
| continue;
|
| }
|
|
|
| @@ -310,8 +272,6 @@ collect_probes (char *objname, char *provider, char *probe_name,
|
|
|
| for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++)
|
| {
|
| - probe_and_objfile_s entry;
|
| -
|
| if (pops != NULL && probe->pops != pops)
|
| continue;
|
|
|
| @@ -323,9 +283,7 @@ collect_probes (char *objname, char *provider, char *probe_name,
|
| && regexec (&probe_pat, probe->name, 0, NULL, 0) != 0)
|
| continue;
|
|
|
| - entry.probe = probe;
|
| - entry.objfile = objfile;
|
| - VEC_safe_push (probe_and_objfile_s, result, &entry);
|
| + VEC_safe_push (probe_p, result, probe);
|
| }
|
| }
|
|
|
| @@ -334,36 +292,36 @@ collect_probes (char *objname, char *provider, char *probe_name,
|
| return result;
|
| }
|
|
|
| -/* A qsort comparison function for probe_and_objfile_s objects. */
|
| +/* A qsort comparison function for probe_p objects. */
|
|
|
| static int
|
| -compare_entries (const void *a, const void *b)
|
| +compare_probes (const void *a, const void *b)
|
| {
|
| - const probe_and_objfile_s *ea = a;
|
| - const probe_and_objfile_s *eb = b;
|
| + const struct probe *pa = *((const struct probe **) a);
|
| + const struct probe *pb = *((const struct probe **) b);
|
| int v;
|
|
|
| - v = strcmp (ea->probe->provider, eb->probe->provider);
|
| + v = strcmp (pa->provider, pb->provider);
|
| if (v)
|
| return v;
|
|
|
| - v = strcmp (ea->probe->name, eb->probe->name);
|
| + v = strcmp (pa->name, pb->name);
|
| if (v)
|
| return v;
|
|
|
| - if (ea->probe->address < eb->probe->address)
|
| + if (pa->address < pb->address)
|
| return -1;
|
| - if (ea->probe->address > eb->probe->address)
|
| + if (pa->address > pb->address)
|
| return 1;
|
|
|
| - return strcmp (ea->objfile->name, eb->objfile->name);
|
| + return strcmp (objfile_name (pa->objfile), objfile_name (pb->objfile));
|
| }
|
|
|
| /* 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 (probe_and_objfile_s) *probes,
|
| +gen_ui_out_table_header_info (VEC (probe_p) *probes,
|
| const struct probe_ops *p)
|
| {
|
| /* `headings' refers to the names of the columns when printing `info
|
| @@ -392,11 +350,11 @@ gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes,
|
| VEC_iterate (info_probe_column_s, headings, ix, column);
|
| ++ix)
|
| {
|
| - probe_and_objfile_s *entry;
|
| + struct probe *probe;
|
| int jx;
|
| size_t size_max = strlen (column->print_name);
|
|
|
| - for (jx = 0; VEC_iterate (probe_and_objfile_s, probes, jx, entry); ++jx)
|
| + for (jx = 0; VEC_iterate (probe_p, probes, jx, probe); ++jx)
|
| {
|
| /* `probe_fields' refers to the values of each new field that this
|
| probe will display. */
|
| @@ -405,12 +363,11 @@ gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes,
|
| const char *val;
|
| int kx;
|
|
|
| - if (entry->probe->pops != p)
|
| + if (probe->pops != p)
|
| continue;
|
|
|
| c2 = make_cleanup (VEC_cleanup (const_char_ptr), &probe_fields);
|
| - p->gen_info_probes_table_values (entry->probe, entry->objfile,
|
| - &probe_fields);
|
| + p->gen_info_probes_table_values (probe, &probe_fields);
|
|
|
| gdb_assert (VEC_length (const_char_ptr, probe_fields)
|
| == headings_size);
|
| @@ -437,10 +394,10 @@ gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes,
|
| }
|
|
|
| /* Helper function to print extra information about a probe and an objfile
|
| - represented by ENTRY. */
|
| + represented by PROBE. */
|
|
|
| static void
|
| -print_ui_out_info (probe_and_objfile_s *entry)
|
| +print_ui_out_info (struct probe *probe)
|
| {
|
| int ix;
|
| int j = 0;
|
| @@ -451,23 +408,21 @@ print_ui_out_info (probe_and_objfile_s *entry)
|
| info_probe_column_s *column;
|
| struct cleanup *c;
|
|
|
| - gdb_assert (entry != NULL);
|
| - gdb_assert (entry->probe != NULL);
|
| - gdb_assert (entry->probe->pops != NULL);
|
| + gdb_assert (probe != NULL);
|
| + gdb_assert (probe->pops != NULL);
|
|
|
| - if (entry->probe->pops->gen_info_probes_table_header == NULL
|
| - && entry->probe->pops->gen_info_probes_table_values == NULL)
|
| + if (probe->pops->gen_info_probes_table_header == NULL
|
| + && probe->pops->gen_info_probes_table_values == NULL)
|
| return;
|
|
|
| - gdb_assert (entry->probe->pops->gen_info_probes_table_header != NULL
|
| - && entry->probe->pops->gen_info_probes_table_values != NULL);
|
| + 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);
|
|
|
| - entry->probe->pops->gen_info_probes_table_header (&headings);
|
| - entry->probe->pops->gen_info_probes_table_values (entry->probe,
|
| - entry->objfile, &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));
|
| @@ -515,16 +470,16 @@ get_number_extra_fields (const struct probe_ops *pops)
|
| void
|
| info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops)
|
| {
|
| - char *provider, *probe = NULL, *objname = NULL;
|
| + char *provider, *probe_name = NULL, *objname = NULL;
|
| struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
|
| - VEC (probe_and_objfile_s) *items;
|
| + VEC (probe_p) *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");
|
| - probe_and_objfile_s *entry;
|
| + struct probe *probe;
|
| struct gdbarch *gdbarch = get_current_arch ();
|
|
|
| /* Do we have a `provider:probe:objfile' style of linespec? */
|
| @@ -533,10 +488,10 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops)
|
| {
|
| make_cleanup (xfree, provider);
|
|
|
| - probe = extract_arg (&arg);
|
| - if (probe)
|
| + probe_name = extract_arg (&arg);
|
| + if (probe_name)
|
| {
|
| - make_cleanup (xfree, probe);
|
| + make_cleanup (xfree, probe_name);
|
|
|
| objname = extract_arg (&arg);
|
| if (objname)
|
| @@ -564,28 +519,27 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops)
|
| else
|
| ui_out_extra_fields = get_number_extra_fields (pops);
|
|
|
| - items = collect_probes (objname, provider, probe, pops);
|
| - make_cleanup (VEC_cleanup (probe_and_objfile_s), &items);
|
| + 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_and_objfile_s, items),
|
| + VEC_length (probe_p, probes),
|
| "StaticProbes");
|
|
|
| - if (!VEC_empty (probe_and_objfile_s, items))
|
| - qsort (VEC_address (probe_and_objfile_s, items),
|
| - VEC_length (probe_and_objfile_s, items),
|
| - sizeof (probe_and_objfile_s), compare_entries);
|
| + if (!VEC_empty (probe_p, probes))
|
| + qsort (VEC_address (probe_p, probes), VEC_length (probe_p, probes),
|
| + sizeof (probe_p), 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_and_objfile_s, items, i, entry); ++i)
|
| + for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i)
|
| {
|
| - size_name = max (strlen (entry->probe->name), size_name);
|
| - size_provider = max (strlen (entry->probe->provider), size_provider);
|
| - size_objname = max (strlen (entry->objfile->name), size_objname);
|
| + size_name = max (strlen (probe->name), size_name);
|
| + size_provider = max (strlen (probe->provider), size_provider);
|
| + size_objname = max (strlen (objfile_name (probe->objfile)), size_objname);
|
| }
|
|
|
| ui_out_table_header (current_uiout, size_provider, ui_left, "provider",
|
| @@ -601,26 +555,26 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops)
|
| /* We have to generate the table header for each new probe type that we
|
| will print. */
|
| for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix)
|
| - gen_ui_out_table_header_info (items, po);
|
| + gen_ui_out_table_header_info (probes, po);
|
| }
|
| else
|
| - gen_ui_out_table_header_info (items, pops);
|
| + gen_ui_out_table_header_info (probes, pops);
|
|
|
| ui_out_table_header (current_uiout, size_objname, ui_left, "object",
|
| _("Object"));
|
| ui_out_table_body (current_uiout);
|
|
|
| - for (i = 0; VEC_iterate (probe_and_objfile_s, items, i, entry); ++i)
|
| + for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i)
|
| {
|
| struct cleanup *inner;
|
|
|
| inner = make_cleanup_ui_out_tuple_begin_end (current_uiout, "probe");
|
|
|
| - ui_out_field_string (current_uiout, "provider", entry->probe->provider);
|
| - ui_out_field_string (current_uiout, "name", entry->probe->name);
|
| + ui_out_field_string (current_uiout, "provider", probe->provider);
|
| + ui_out_field_string (current_uiout, "name", probe->name);
|
| ui_out_field_core_addr (current_uiout, "addr",
|
| - get_objfile_arch (entry->objfile),
|
| - entry->probe->address);
|
| + get_objfile_arch (probe->objfile),
|
| + probe->address);
|
|
|
| if (pops == NULL)
|
| {
|
| @@ -629,19 +583,20 @@ 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 (entry->probe->pops == po)
|
| - print_ui_out_info (entry);
|
| + if (probe->pops == po)
|
| + print_ui_out_info (probe);
|
| }
|
| else
|
| - print_ui_out_info (entry);
|
| + print_ui_out_info (probe);
|
|
|
| - ui_out_field_string (current_uiout, "object", entry->objfile->name);
|
| + ui_out_field_string (current_uiout, "object",
|
| + objfile_name (probe->objfile));
|
| ui_out_text (current_uiout, "\n");
|
|
|
| do_cleanups (inner);
|
| }
|
|
|
| - any_found = !VEC_empty (probe_and_objfile_s, items);
|
| + any_found = !VEC_empty (probe_p, probes);
|
| do_cleanups (cleanup);
|
|
|
| if (!any_found)
|
| @@ -658,27 +613,45 @@ info_probes_command (char *arg, int from_tty)
|
|
|
| /* See comments in probe.h. */
|
|
|
| +unsigned
|
| +get_probe_argument_count (struct probe *probe)
|
| +{
|
| + return probe->pops->get_probe_argument_count (probe);
|
| +}
|
| +
|
| +/* 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)
|
| +{
|
| + return probe->pops->evaluate_probe_argument (probe, n);
|
| +}
|
| +
|
| +/* See comments in probe.h. */
|
| +
|
| struct value *
|
| probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n)
|
| {
|
| struct probe *probe;
|
| - struct objfile *objfile;
|
| - unsigned n_probes;
|
| + unsigned n_args;
|
|
|
| - probe = find_probe_by_pc (get_frame_pc (frame), &objfile);
|
| + probe = find_probe_by_pc (get_frame_pc (frame));
|
| if (!probe)
|
| return NULL;
|
| - gdb_assert (objfile->sf && objfile->sf->sym_probe_fns);
|
|
|
| - n_probes
|
| - = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile,
|
| - probe);
|
| - if (n >= n_probes)
|
| + n_args = get_probe_argument_count (probe);
|
| + if (n >= n_args)
|
| return NULL;
|
|
|
| - return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile,
|
| - probe,
|
| - n);
|
| + return evaluate_probe_argument (probe, n);
|
| }
|
|
|
| /* See comment in probe.h. */
|
|
|