Adapt `info probes' to support printing probes of different types.
A "probe type" (backend for the probe abstraction implemented in probe.[ch]) can extend the information printed by `info probes' by defining additional columns. This means that when `info probes' is used to print all the probes regardless of their types, some of the columns will be "not applicable" to some of the probes (like, say, the Semaphore column only makes sense for SystemTap probes). This patch makes `info probes' fill these slots with "n/a" marks (currently it breaks the table) and not include headers for which no actual probe has been found in the list of defined probes. This patch also adds support for a new generic column "Type", that displays the type of each probe. SystemTap probes identify themselves as "stap" probes. gdb/ChangeLog: 2015-02-17 Jose E. Marchesi <jose.marchesi@oracle.com> * probe.c (print_ui_out_not_applicables): New function. (exists_probe_with_pops): Likewise. (info_probes_for_ops): Do not include column headers for probe types for which no probe has been actually found on any object. Also invoke `print_ui_out_not_applicables' in order to match the column rows with the header when probes of several types are listed. Print the "Type" column. * probe.h (probe_ops): Added a new probe operation `type_name'. * stap-probe.c (stap_probe_ops): Add `stap_type_name'. (stap_type_name): New function.
This commit is contained in:
parent
2ec55de302
commit
6f9b84910f
@ -1,3 +1,17 @@
|
||||
2015-02-17 Jose E. Marchesi <jose.marchesi@oracle.com>
|
||||
|
||||
* probe.c (print_ui_out_not_applicables): New function.
|
||||
(exists_probe_with_pops): Likewise.
|
||||
(info_probes_for_ops): Do not include column headers for probe
|
||||
types for which no probe has been actually found on any object.
|
||||
Also invoke `print_ui_out_not_applicables' in order to match the
|
||||
column rows with the header when probes of several types are
|
||||
listed.
|
||||
Print the "Type" column.
|
||||
* probe.h (probe_ops): Added a new probe operation `type_name'.
|
||||
* stap-probe.c (stap_probe_ops): Add `stap_type_name'.
|
||||
(stap_type_name): New function.
|
||||
|
||||
2015-02-17 Patrick Palka <patrick@parcs.ath.cx>
|
||||
|
||||
* tui/tui-io.c (tui_getc): Don't call key_is_command_char.
|
||||
|
76
gdb/probe.c
76
gdb/probe.c
@ -410,6 +410,31 @@ gen_ui_out_table_header_info (VEC (bound_probe_s) *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. */
|
||||
|
||||
@ -482,6 +507,23 @@ 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;
|
||||
}
|
||||
|
||||
/* See comment in probe.h. */
|
||||
|
||||
void
|
||||
@ -497,6 +539,7 @@ info_probes_for_ops (const char *arg, int from_tty,
|
||||
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 ();
|
||||
|
||||
@ -517,6 +560,9 @@ info_probes_for_ops (const char *arg, int from_tty,
|
||||
}
|
||||
}
|
||||
|
||||
probes = collect_probes (objname, provider, probe_name, pops);
|
||||
make_cleanup (VEC_cleanup (probe_p), &probes);
|
||||
|
||||
if (pops == NULL)
|
||||
{
|
||||
const struct probe_ops *po;
|
||||
@ -529,18 +575,18 @@ info_probes_for_ops (const char *arg, int from_tty,
|
||||
|
||||
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,
|
||||
5 + ui_out_extra_fields,
|
||||
VEC_length (bound_probe_s, probes),
|
||||
"StaticProbes");
|
||||
|
||||
@ -552,15 +598,19 @@ info_probes_for_ops (const char *arg, int from_tty,
|
||||
/* 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'). */
|
||||
/* 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 = 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"));
|
||||
@ -571,10 +621,12 @@ info_probes_for_ops (const char *arg, int from_tty,
|
||||
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);
|
||||
@ -586,9 +638,11 @@ info_probes_for_ops (const char *arg, int from_tty,
|
||||
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, "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",
|
||||
@ -604,6 +658,8 @@ info_probes_for_ops (const char *arg, int from_tty,
|
||||
++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);
|
||||
|
@ -113,6 +113,12 @@ struct probe_ops
|
||||
|
||||
void (*destroy) (struct probe *probe);
|
||||
|
||||
/* Return a pointer to a name identifying the probe type. This is
|
||||
the string that will be displayed in the "Type" column of the
|
||||
`info probes' command. */
|
||||
|
||||
const char *(*type_name) (struct probe *probe);
|
||||
|
||||
/* Function responsible for providing the extra fields that will be
|
||||
printed in the `info probes' command. It should fill HEADS
|
||||
with whatever extra fields it needs. If the backend doesn't need
|
||||
|
@ -1703,6 +1703,15 @@ stap_get_probes (VEC (probe_p) **probesp, struct objfile *objfile)
|
||||
}
|
||||
}
|
||||
|
||||
/* Implementation of the type_name method. */
|
||||
|
||||
static const char *
|
||||
stap_type_name (struct probe *probe)
|
||||
{
|
||||
gdb_assert (probe->pops == &stap_probe_ops);
|
||||
return "stap";
|
||||
}
|
||||
|
||||
static int
|
||||
stap_probe_is_linespec (const char **linespecp)
|
||||
{
|
||||
@ -1754,6 +1763,7 @@ const struct probe_ops stap_probe_ops =
|
||||
stap_set_semaphore,
|
||||
stap_clear_semaphore,
|
||||
stap_probe_destroy,
|
||||
stap_type_name,
|
||||
stap_gen_info_probes_table_header,
|
||||
stap_gen_info_probes_table_values,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user