[gdb/cli] Add maintenance ignore-probes

There's a command "disable probes", but SystemTap probes, for instance
libc:longjmp cannot be disabled:
...
$ gdb -q -batch a.out -ex start -ex "disable probes libc ^longjmp$"
  ...
Probe libc:longjmp cannot be disabled.
Probe libc:longjmp cannot be disabled.
Probe libc:longjmp cannot be disabled.
...

Add a command "maintenance ignore-probes" that ignores probes during
get_probes, such that we can easily pretend to use a libc without the
libc:longjmp probe:
...
(gdb) maint ignore-probes -verbose libc ^longjmp$
ignore-probes filter has been set to:
PROVIDER: 'libc'
PROBE_NAME: '^longjmp$'
OBJNAME: ''
(gdb) start ^M
  ...
Ignoring SystemTap probe libc longjmp in /lib64/libc.so.6.^M
Ignoring SystemTap probe libc longjmp in /lib64/libc.so.6.^M
Ignoring SystemTap probe libc longjmp in /lib64/libc.so.6.^M
...

The "Ignoring ..." messages can be suppressed by not using -verbose.

Note that as with "disable probes", running simply "maint ignore-probes"
ignores all probes.

The ignore-probes filter can be reset by using:
...
(gdb) maint ignore-probes -reset
ignore-probes filter has been reset
...

For now, the command is only supported for SystemTap probes.

PR cli/27159
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=27159
This commit is contained in:
Tom de Vries
2022-12-31 10:23:06 +01:00
parent a667697f36
commit 08c59458a1
4 changed files with 145 additions and 0 deletions

View File

@@ -6114,6 +6114,7 @@ disabled, but @code{SystemTap} probes cannot be disabled.
You can enable (or disable) one or more probes using the following
commands, with optional arguments:
@anchor{enable probes}
@table @code
@kindex enable probes
@item enable probes @r{[}@var{provider} @r{[}@var{name} @r{[}@var{objfile}@r{]}@r{]}@r{]}
@@ -40897,6 +40898,27 @@ Like the @code{with} command, but works with @code{maintenance set}
variables. This is used by the testsuite to exercise the @code{with}
command's infrastructure.
@kindex maint ignore-probes
@item maint ignore-probes [@var{-v}|@var{-verbose}] [@var{provider} [@var{name} [@var{objfile}]]]
@itemx maint ignore-probes @var{-reset}
Set or reset the ignore-probes filter. The @var{provider}, @var{name}
and @var{objfile} arguments are as in @code{enable probes} and
@code{disable probes} (@pxref{enable probes}). Only supported for
SystemTap probes.
Here's an example of using @code{maint ignore-probes}:
@smallexample
(gdb) maint ignore-probes -verbose libc ^longjmp$
ignore-probes filter has been set to:
PROVIDER: 'libc'
PROBE_NAME: '^longjmp$'
OBJNAME: ''
(gdb) start
<... more output ...>
Ignoring SystemTap probe libc longjmp in /lib64/libc.so.6.^M
Ignoring SystemTap probe libc longjmp in /lib64/libc.so.6.^M
Ignoring SystemTap probe libc longjmp in /lib64/libc.so.6.^M
@end smallexample
@end table
The following command is useful for non-interactive invocations of

View File

@@ -680,6 +680,109 @@ disable_probes_command (const char *arg, int from_tty)
}
}
static bool ignore_probes_p = false;
static bool ignore_probes_idx = 0;
static bool ignore_probes_verbose_p;
static gdb::optional<compiled_regex> ignore_probes_prov_pat[2];
static gdb::optional<compiled_regex> ignore_probes_name_pat[2];
static gdb::optional<compiled_regex> ignore_probes_obj_pat[2];
/* See comments in probe.h. */
bool
ignore_probe_p (const char *provider, const char *name,
const char *objfile_name, const char *type)
{
if (!ignore_probes_p)
return false;
gdb::optional<compiled_regex> &re_prov
= ignore_probes_prov_pat[ignore_probes_idx];
gdb::optional<compiled_regex> &re_name
= ignore_probes_name_pat[ignore_probes_idx];
gdb::optional<compiled_regex> &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;
}
/* Implementation of the `maintenance ignore-probes' command. */
static void
ignore_probes_command (const char *arg, int from_tty)
{
std::string ignore_provider, ignore_probe_name, ignore_objname;
bool verbose_p = false;
if (arg != nullptr)
{
const char *idx = arg;
std::string s = extract_arg (&idx);
if (strcmp (s.c_str (), "-reset") == 0)
{
if (*idx != '\0')
error (_("-reset: no arguments allowed"));
ignore_probes_p = false;
gdb_printf (gdb_stdout, _("ignore-probes filter has been reset\n"));
return;
}
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;
gdb::optional<compiled_regex> &re_prov
= ignore_probes_prov_pat[new_ignore_probes_idx];
gdb::optional<compiled_regex> &re_name
= ignore_probes_name_pat[new_ignore_probes_idx];
gdb::optional<compiled_regex> &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 *
@@ -931,4 +1034,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);
}

View File

@@ -304,4 +304,9 @@ extern struct cmd_list_element **info_probes_cmdlist_get (void);
extern struct value *probe_safe_evaluate_at_pc (frame_info_ptr frame,
unsigned n);
/* Return true if the PROVIDER/NAME probe from OBJFILE_NAME needs to be
ignored. */
bool ignore_probe_p (const char *provider, const char *name,
const char *objfile_name, const char *TYPE);
#endif /* !defined (PROBE_H) */

View File

@@ -1619,6 +1619,9 @@ handle_stap_probe (struct objfile *objfile, struct sdt_note *el,
return;
}
if (ignore_probe_p (provider, name, objfile_name (objfile), "SystemTap"))
return;
stap_probe *ret = new stap_probe (std::string (name), std::string (provider),
address, gdbarch, sem_addr, probe_args);