Introduce compiled_regex, eliminate make_regfree_cleanup

This patch replaces compile_rx_or_error and make_regfree_cleanup with
a class that wraps a regex_t.

gdb/ChangeLog:
2017-06-07  Pedro Alves  <palves@redhat.com>

	* Makefile.in (SFILES): Add gdb_regex.c.
	(COMMON_OBS): Add gdb_regex.o.
	* ada-lang.c (ada_add_standard_exceptions)
	(ada_add_exceptions_from_frame, name_matches_regex)
	(ada_add_global_exceptions, ada_exceptions_list_1): Change regex
	parameter type to compiled_regex.  Adjust.
	(ada_exceptions_list): Use compiled_regex.
	* break-catch-throw.c (exception_catchpoint::pattern): Now a
	std::unique_ptr<compiled_regex>.
	(exception_catchpoint::~exception_catchpoint): Remove regfree
	call.
	(check_status_exception_catchpoint): Adjust to use compiled_regex.
	(handle_gnu_v3_exceptions): Adjust to use compiled_regex.
	* breakpoint.c (solib_catchpoint::compiled): Now a
	std::unique_ptr<compiled_regex>.
	(solib_catchpoint::~solib_catchpoint): Remove regfree call.
	(check_status_catch_solib): Adjust to use compiled_regex.
	(add_solib_catchpoint): Adjust to use compiled_regex.
	* cli/cli-cmds.c (apropos_command): Use compiled_regex.
	* cli/cli-decode.c (apropos_cmd): Change regex parameter to
	compiled_regex reference.  Adjust to use it.
	* cli/cli-decode.h: Remove struct re_pattern_buffer forward
	declaration.  Include "gdb_regex.h".
	(apropos_cmd): Change regex parameter to compiled_regex reference.
	* gdb_regex.c: New file.
	* gdb_regex.h (make_regfree_cleanup, get_regcomp_error): Delete
	declarations.
	(class compiled_regex): New.
	* linux-tdep.c: Include "common/gdb_optional.h".
	(struct mapping_regexes): New, factored out from
	mapping_is_anonymous_p, and adjusted to use compiled_regex.
	(mapping_is_anonymous_p): Use mapping_regexes wrapped in a
	gdb::optional and remove cleanups.  Adjust to compiled_regex.
	* probe.c: Include "common/gdb_optional.h".
	(collect_probes): Use compiled_regex and gdb::optional and remove
	cleanups.
	* skip.c: Include "common/gdb_optional.h".
	(skiplist_entry::compiled_function_regexp): Now a
	gdb::optional<compiled_regex>.
	(skiplist_entry::compiled_function_regexp_is_valid): Delete field.
	(free_skiplist_entry): Remove regfree call.
	(compile_skip_regexp, skip_rfunction_p): Adjust to use
	compiled_regex and gdb::optional.
	* symtab.c: Include "common/gdb_optional.h".
	(search_symbols): Use compiled_regex and gdb::optional.
	* utils.c (do_regfree_cleanup, make_regfree_cleanup)
	(get_regcomp_error, compile_rx_or_error): Delete.  Some bits moved
	to gdb_regex.c.
This commit is contained in:
Pedro Alves 2017-06-07 14:21:40 +01:00
parent 62e20ed45e
commit 2d7cc5c797
15 changed files with 255 additions and 226 deletions

View File

@ -1,3 +1,54 @@
2017-06-07 Pedro Alves <palves@redhat.com>
* Makefile.in (SFILES): Add gdb_regex.c.
(COMMON_OBS): Add gdb_regex.o.
* ada-lang.c (ada_add_standard_exceptions)
(ada_add_exceptions_from_frame, name_matches_regex)
(ada_add_global_exceptions, ada_exceptions_list_1): Change regex
parameter type to compiled_regex. Adjust.
(ada_exceptions_list): Use compiled_regex.
* break-catch-throw.c (exception_catchpoint::pattern): Now a
std::unique_ptr<compiled_regex>.
(exception_catchpoint::~exception_catchpoint): Remove regfree
call.
(check_status_exception_catchpoint): Adjust to use compiled_regex.
(handle_gnu_v3_exceptions): Adjust to use compiled_regex.
* breakpoint.c (solib_catchpoint::compiled): Now a
std::unique_ptr<compiled_regex>.
(solib_catchpoint::~solib_catchpoint): Remove regfree call.
(check_status_catch_solib): Adjust to use compiled_regex.
(add_solib_catchpoint): Adjust to use compiled_regex.
* cli/cli-cmds.c (apropos_command): Use compiled_regex.
* cli/cli-decode.c (apropos_cmd): Change regex parameter to
compiled_regex reference. Adjust to use it.
* cli/cli-decode.h: Remove struct re_pattern_buffer forward
declaration. Include "gdb_regex.h".
(apropos_cmd): Change regex parameter to compiled_regex reference.
* gdb_regex.c: New file.
* gdb_regex.h (make_regfree_cleanup, get_regcomp_error): Delete
declarations.
(class compiled_regex): New.
* linux-tdep.c: Include "common/gdb_optional.h".
(struct mapping_regexes): New, factored out from
mapping_is_anonymous_p, and adjusted to use compiled_regex.
(mapping_is_anonymous_p): Use mapping_regexes wrapped in a
gdb::optional and remove cleanups. Adjust to compiled_regex.
* probe.c: Include "common/gdb_optional.h".
(collect_probes): Use compiled_regex and gdb::optional and remove
cleanups.
* skip.c: Include "common/gdb_optional.h".
(skiplist_entry::compiled_function_regexp): Now a
gdb::optional<compiled_regex>.
(skiplist_entry::compiled_function_regexp_is_valid): Delete field.
(free_skiplist_entry): Remove regfree call.
(compile_skip_regexp, skip_rfunction_p): Adjust to use
compiled_regex and gdb::optional.
* symtab.c: Include "common/gdb_optional.h".
(search_symbols): Use compiled_regex and gdb::optional.
* utils.c (do_regfree_cleanup, make_regfree_cleanup)
(get_regcomp_error, compile_rx_or_error): Delete. Some bits moved
to gdb_regex.c.
2017-06-07 Alan Hayward <alan.hayward@arm.com>
* regcache.c (regcache::save): Avoid buffer use.

View File

@ -1104,6 +1104,7 @@ SFILES = \
gdb_bfd.c \
gdb-dlfcn.c \
gdb_obstack.c \
gdb_regex.c \
gdb_usleep.c \
gdbarch.c \
gdbarch-selftests.c \
@ -1717,6 +1718,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
gdb_bfd.o \
gdb-dlfcn.o \
gdb_obstack.o \
gdb_regex.o \
gdb_usleep.o \
gdb_vecs.o \
gdbarch.o \

View File

@ -13219,14 +13219,15 @@ sort_remove_dups_ada_exceptions_list (VEC(ada_exc_info) **exceptions,
gets pushed. */
static void
ada_add_standard_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
ada_add_standard_exceptions (compiled_regex *preg,
VEC(ada_exc_info) **exceptions)
{
int i;
for (i = 0; i < ARRAY_SIZE (standard_exc); i++)
{
if (preg == NULL
|| regexec (preg, standard_exc[i], 0, NULL, 0) == 0)
|| preg->exec (standard_exc[i], 0, NULL, 0) == 0)
{
struct bound_minimal_symbol msymbol
= ada_lookup_simple_minsym (standard_exc[i]);
@ -13253,7 +13254,8 @@ ada_add_standard_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
gets pushed. */
static void
ada_add_exceptions_from_frame (regex_t *preg, struct frame_info *frame,
ada_add_exceptions_from_frame (compiled_regex *preg,
struct frame_info *frame,
VEC(ada_exc_info) **exceptions)
{
const struct block *block = get_frame_block (frame, 0);
@ -13290,10 +13292,10 @@ ada_add_exceptions_from_frame (regex_t *preg, struct frame_info *frame,
/* Return true if NAME matches PREG or if PREG is NULL. */
static bool
name_matches_regex (const char *name, regex_t *preg)
name_matches_regex (const char *name, compiled_regex *preg)
{
return (preg == NULL
|| regexec (preg, ada_decode (name), 0, NULL, 0) == 0);
|| preg->exec (ada_decode (name), 0, NULL, 0) == 0);
}
/* Add all exceptions defined globally whose name name match
@ -13316,7 +13318,8 @@ name_matches_regex (const char *name, regex_t *preg)
gets pushed. */
static void
ada_add_global_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
ada_add_global_exceptions (compiled_regex *preg,
VEC(ada_exc_info) **exceptions)
{
struct objfile *objfile;
struct compunit_symtab *s;
@ -13364,7 +13367,7 @@ ada_add_global_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
do not match. Otherwise, all exceptions are listed. */
static VEC(ada_exc_info) *
ada_exceptions_list_1 (regex_t *preg)
ada_exceptions_list_1 (compiled_regex *preg)
{
VEC(ada_exc_info) *result = NULL;
struct cleanup *old_chain
@ -13417,19 +13420,11 @@ ada_exceptions_list_1 (regex_t *preg)
VEC(ada_exc_info) *
ada_exceptions_list (const char *regexp)
{
VEC(ada_exc_info) *result = NULL;
struct cleanup *old_chain = NULL;
regex_t reg;
if (regexp == NULL)
return ada_exceptions_list_1 (NULL);
if (regexp != NULL)
old_chain = compile_rx_or_error (&reg, regexp,
_("invalid regular expression"));
result = ada_exceptions_list_1 (regexp != NULL ? &reg : NULL);
if (old_chain != NULL)
do_cleanups (old_chain);
return result;
compiled_regex reg (regexp, REG_NOSUB, _("invalid regular expression"));
return ada_exceptions_list_1 (&reg);
}
/* Implement the "info exceptions" command. */

View File

@ -87,10 +87,10 @@ struct exception_catchpoint : public breakpoint
char *exception_rx;
/* If non-NULL, an xmalloc'd, compiled regular expression which is
used to determine which exceptions to stop on. */
/* If non-NULL, a compiled regular expression which is used to
determine which exceptions to stop on. */
regex_t *pattern;
std::unique_ptr<compiled_regex> pattern;
};
@ -145,8 +145,6 @@ classify_exception_breakpoint (struct breakpoint *b)
exception_catchpoint::~exception_catchpoint ()
{
xfree (this->exception_rx);
if (this->pattern != NULL)
regfree (this->pattern);
}
/* Implement the 'check_status' method. */
@ -185,7 +183,7 @@ check_status_exception_catchpoint (struct bpstats *bs)
if (!type_name.empty ())
{
if (regexec (self->pattern, type_name.c_str (), 0, NULL, 0) != 0)
if (self->pattern->exec (type_name.c_str (), 0, NULL, 0) != 0)
bs->stop = 0;
}
}
@ -377,15 +375,12 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx,
const char *cond_string,
enum exception_event_kind ex_event, int from_tty)
{
regex_t *pattern = NULL;
std::unique_ptr<compiled_regex> pattern;
if (except_rx != NULL)
{
pattern = XNEW (regex_t);
make_cleanup (xfree, pattern);
compile_rx_or_error (pattern, except_rx,
_("invalid type-matching regexp"));
pattern.reset (new compiled_regex (except_rx, REG_NOSUB,
_("invalid type-matching regexp")));
}
std::unique_ptr<exception_catchpoint> cp (new exception_catchpoint ());
@ -397,7 +392,7 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx,
cp->type = bp_breakpoint;
cp->kind = ex_event;
cp->exception_rx = except_rx;
cp->pattern = pattern;
cp->pattern = std::move (pattern);
re_set_exception_catchpoint (cp.get ());

View File

@ -8284,13 +8284,11 @@ struct solib_catchpoint : public breakpoint
/* Regular expression to match, if any. COMPILED is only valid when
REGEX is non-NULL. */
char *regex;
regex_t compiled;
std::unique_ptr<compiled_regex> compiled;
};
solib_catchpoint::~solib_catchpoint ()
{
if (this->regex)
regfree (&this->compiled);
xfree (this->regex);
}
@ -8358,7 +8356,7 @@ check_status_catch_solib (struct bpstats *bs)
++ix)
{
if (!self->regex
|| regexec (&self->compiled, iter->so_name, 0, NULL, 0) == 0)
|| self->compiled->exec (iter->so_name, 0, NULL, 0) == 0)
return;
}
}
@ -8372,7 +8370,7 @@ check_status_catch_solib (struct bpstats *bs)
++ix)
{
if (!self->regex
|| regexec (&self->compiled, iter, 0, NULL, 0) == 0)
|| self->compiled->exec (iter, 0, NULL, 0) == 0)
return;
}
}
@ -8488,16 +8486,8 @@ add_solib_catchpoint (const char *arg, int is_load, int is_temp, int enabled)
if (*arg != '\0')
{
int errcode;
errcode = regcomp (&c->compiled, arg, REG_NOSUB);
if (errcode != 0)
{
char *err = get_regcomp_error (errcode, &c->compiled);
make_cleanup (xfree, err);
error (_("Invalid regexp (%s): %s"), err, arg);
}
c->compiled.reset (new compiled_regex (arg, REG_NOSUB,
_("Invalid regexp")));
c->regex = xstrdup (arg);
}

View File

@ -1336,28 +1336,13 @@ show_user (char *args, int from_tty)
static void
apropos_command (char *searchstr, int from_tty)
{
regex_t pattern;
int code;
if (searchstr == NULL)
error (_("REGEXP string is empty"));
code = regcomp (&pattern, searchstr, REG_ICASE);
if (code == 0)
{
struct cleanup *cleanups;
compiled_regex pattern (searchstr, REG_ICASE,
_("Error in regular expression"));
cleanups = make_regfree_cleanup (&pattern);
apropos_cmd (gdb_stdout, cmdlist, &pattern, "");
do_cleanups (cleanups);
}
else
{
char *err = get_regcomp_error (code, &pattern);
make_cleanup (xfree, err);
error (_("Error in regular expression: %s"), err);
}
apropos_cmd (gdb_stdout, cmdlist, pattern, "");
}
/* Subroutine of alias_command to simplify it.

View File

@ -917,7 +917,7 @@ add_com_suppress_notification (const char *name, enum command_class theclass,
void
apropos_cmd (struct ui_file *stream,
struct cmd_list_element *commandlist,
struct re_pattern_buffer *regex, const char *prefix)
compiled_regex &regex, const char *prefix)
{
struct cmd_list_element *c;
int returnvalue;
@ -928,9 +928,10 @@ apropos_cmd (struct ui_file *stream,
returnvalue = -1; /* Needed to avoid double printing. */
if (c->name != NULL)
{
size_t name_len = strlen (c->name);
/* Try to match against the name. */
returnvalue = re_search (regex, c->name, strlen(c->name),
0, strlen (c->name), NULL);
returnvalue = regex.search (c->name, name_len, 0, name_len, NULL);
if (returnvalue >= 0)
{
print_help_for_command (c, prefix,
@ -939,8 +940,10 @@ apropos_cmd (struct ui_file *stream,
}
if (c->doc != NULL && returnvalue < 0)
{
size_t doc_len = strlen (c->doc);
/* Try to match against documentation. */
if (re_search(regex,c->doc,strlen(c->doc),0,strlen(c->doc),NULL) >=0)
if (regex.search (c->doc, doc_len, 0, doc_len, NULL) >= 0)
{
print_help_for_command (c, prefix,
0 /* don't recurse */, stream);

View File

@ -23,8 +23,7 @@
/* Include the public interfaces. */
#include "command.h"
struct re_pattern_buffer;
#include "gdb_regex.h"
#if 0
/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum
@ -234,7 +233,7 @@ extern void help_cmd_list (struct cmd_list_element *, enum command_class,
extern void help_cmd (const char *, struct ui_file *);
extern void apropos_cmd (struct ui_file *, struct cmd_list_element *,
struct re_pattern_buffer *, const char *);
compiled_regex &, const char *);
/* Used to mark commands that don't do anything. If we just leave the
function field NULL, the command is interpreted as a help topic, or

56
gdb/gdb_regex.c Normal file
View File

@ -0,0 +1,56 @@
/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "gdb_regex.h"
compiled_regex::compiled_regex (const char *regex, int cflags,
const char *message)
{
gdb_assert (regex != NULL);
gdb_assert (message != NULL);
int code = regcomp (&m_pattern, regex, cflags);
if (code != 0)
{
size_t length = regerror (code, &m_pattern, NULL, 0);
std::unique_ptr<char[]> err (new char[length]);
regerror (code, &m_pattern, err.get (), length);
error (("%s: %s"), message, err.get ());
}
}
compiled_regex::~compiled_regex ()
{
regfree (&m_pattern);
}
int
compiled_regex::exec (const char *string, size_t nmatch,
regmatch_t pmatch[], int eflags) const
{
return regexec (&m_pattern, string, nmatch, pmatch, eflags);
}
int
compiled_regex::search (const char *string,
int length, int start, int range,
struct re_registers *regs)
{
return re_search (&m_pattern, string, length, start, range, regs);
}

View File

@ -27,10 +27,39 @@
# include <regex.h>
#endif
/* From utils.c. */
struct cleanup *make_regfree_cleanup (regex_t *);
char *get_regcomp_error (int, regex_t *);
struct cleanup *compile_rx_or_error (regex_t *pattern, const char *rx,
const char *message);
/* A compiled regex. This is mainly a wrapper around regex_t. The
the constructor throws on regcomp error and the destructor is
responsible for calling regfree. The former means that it's not
possible to create an instance of compiled_regex that isn't
compiled, hence the name. */
class compiled_regex
{
public:
/* Compile a regexp and throw an exception on error, including
MESSAGE. REGEX and MESSAGE must not be NULL. */
compiled_regex (const char *regex, int cflags,
const char *message)
ATTRIBUTE_NONNULL (2) ATTRIBUTE_NONNULL (4);
~compiled_regex ();
/* Disable copy. */
compiled_regex (const compiled_regex&) = delete;
void operator= (const compiled_regex&) = delete;
/* Wrapper around ::regexec. */
int exec (const char *string,
size_t nmatch, regmatch_t pmatch[],
int eflags) const;
/* Wrapper around ::re_search. (Not const because re_search's
regex_t parameter isn't either.) */
int search (const char *string, int size, int startpos,
int range, struct re_registers *regs);
private:
/* The compiled pattern. */
regex_t m_pattern;
};
#endif /* not GDB_REGEX_H */

View File

@ -38,6 +38,7 @@
#include "gdbcmd.h"
#include "gdb_regex.h"
#include "common/enum-flags.h"
#include "common/gdb_optional.h"
#include <ctype.h>
@ -493,6 +494,44 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
}
}
/* Regexes used by mapping_is_anonymous_p. Put in a structure because
they're initialized lazily. */
struct mapping_regexes
{
/* Matches "/dev/zero" filenames (with or without the "(deleted)"
string in the end). We know for sure, based on the Linux kernel
code, that memory mappings whose associated filename is
"/dev/zero" are guaranteed to be MAP_ANONYMOUS. */
compiled_regex dev_zero
{"^/dev/zero\\( (deleted)\\)\\?$", REG_NOSUB,
_("Could not compile regex to match /dev/zero filename")};
/* Matches "/SYSV%08x" filenames (with or without the "(deleted)"
string in the end). These filenames refer to shared memory
(shmem), and memory mappings associated with them are
MAP_ANONYMOUS as well. */
compiled_regex shmem_file
{"^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$", REG_NOSUB,
_("Could not compile regex to match shmem filenames")};
/* A heuristic we use to try to mimic the Linux kernel's 'n_link ==
0' code, which is responsible to decide if it is dealing with a
'MAP_SHARED | MAP_ANONYMOUS' mapping. In other words, if
FILE_DELETED matches, it does not necessarily mean that we are
dealing with an anonymous shared mapping. However, there is no
easy way to detect this currently, so this is the best
approximation we have.
As a result, GDB will dump readonly pages of deleted executables
when using the default value of coredump_filter (0x33), while the
Linux kernel will not dump those pages. But we can live with
that. */
compiled_regex file_deleted
{" (deleted)$", REG_NOSUB,
_("Could not compile regex to match '<file> (deleted)'")};
};
/* Return 1 if the memory mapping is anonymous, 0 otherwise.
FILENAME is the name of the file present in the first line of the
@ -506,52 +545,16 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
static int
mapping_is_anonymous_p (const char *filename)
{
static regex_t dev_zero_regex, shmem_file_regex, file_deleted_regex;
static gdb::optional<mapping_regexes> regexes;
static int init_regex_p = 0;
if (!init_regex_p)
{
struct cleanup *c = make_cleanup (null_cleanup, NULL);
/* Let's be pessimistic and assume there will be an error while
compiling the regex'es. */
init_regex_p = -1;
/* DEV_ZERO_REGEX matches "/dev/zero" filenames (with or
without the "(deleted)" string in the end). We know for
sure, based on the Linux kernel code, that memory mappings
whose associated filename is "/dev/zero" are guaranteed to be
MAP_ANONYMOUS. */
compile_rx_or_error (&dev_zero_regex, "^/dev/zero\\( (deleted)\\)\\?$",
_("Could not compile regex to match /dev/zero "
"filename"));
/* SHMEM_FILE_REGEX matches "/SYSV%08x" filenames (with or
without the "(deleted)" string in the end). These filenames
refer to shared memory (shmem), and memory mappings
associated with them are MAP_ANONYMOUS as well. */
compile_rx_or_error (&shmem_file_regex,
"^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$",
_("Could not compile regex to match shmem "
"filenames"));
/* FILE_DELETED_REGEX is a heuristic we use to try to mimic the
Linux kernel's 'n_link == 0' code, which is responsible to
decide if it is dealing with a 'MAP_SHARED | MAP_ANONYMOUS'
mapping. In other words, if FILE_DELETED_REGEX matches, it
does not necessarily mean that we are dealing with an
anonymous shared mapping. However, there is no easy way to
detect this currently, so this is the best approximation we
have.
As a result, GDB will dump readonly pages of deleted
executables when using the default value of coredump_filter
(0x33), while the Linux kernel will not dump those pages.
But we can live with that. */
compile_rx_or_error (&file_deleted_regex, " (deleted)$",
_("Could not compile regex to match "
"'<file> (deleted)'"));
/* We will never release these regexes, so just discard the
cleanups. */
discard_cleanups (c);
regexes.emplace ();
/* If we reached this point, then everything succeeded. */
init_regex_p = 1;
@ -573,9 +576,9 @@ mapping_is_anonymous_p (const char *filename)
}
if (*filename == '\0'
|| regexec (&dev_zero_regex, filename, 0, NULL, 0) == 0
|| regexec (&shmem_file_regex, filename, 0, NULL, 0) == 0
|| regexec (&file_deleted_regex, filename, 0, NULL, 0) == 0)
|| regexes->dev_zero.exec (filename, 0, NULL, 0) == 0
|| regexes->shmem_file.exec (filename, 0, NULL, 0) == 0
|| regexes->file_deleted.exec (filename, 0, NULL, 0) == 0)
return 1;
return 0;

View File

@ -36,6 +36,7 @@
#include "location.h"
#include <ctype.h>
#include <algorithm>
#include "common/gdb_optional.h"
typedef struct bound_probe bound_probe_s;
DEF_VEC_O (bound_probe_s);
@ -288,18 +289,17 @@ collect_probes (char *objname, char *provider, char *probe_name,
{
struct objfile *objfile;
VEC (bound_probe_s) *result = NULL;
struct cleanup *cleanup, *cleanup_temps;
regex_t obj_pat, prov_pat, probe_pat;
struct cleanup *cleanup;
gdb::optional<compiled_regex> 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"));
prov_pat.emplace (provider, REG_NOSUB, _("Invalid provider regexp"));
if (probe_name != NULL)
compile_rx_or_error (&probe_pat, probe_name, _("Invalid probe regexp"));
probe_pat.emplace (probe_name, REG_NOSUB, _("Invalid probe regexp"));
if (objname != NULL)
compile_rx_or_error (&obj_pat, objname, _("Invalid object file regexp"));
obj_pat.emplace (objname, REG_NOSUB, _("Invalid object file regexp"));
ALL_OBJFILES (objfile)
{
@ -312,7 +312,7 @@ collect_probes (char *objname, char *provider, char *probe_name,
if (objname)
{
if (regexec (&obj_pat, objfile_name (objfile), 0, NULL, 0) != 0)
if (obj_pat->exec (objfile_name (objfile), 0, NULL, 0) != 0)
continue;
}
@ -326,11 +326,11 @@ collect_probes (char *objname, char *provider, char *probe_name,
continue;
if (provider
&& regexec (&prov_pat, probe->provider, 0, NULL, 0) != 0)
&& prov_pat->exec (probe->provider, 0, NULL, 0) != 0)
continue;
if (probe_name
&& regexec (&probe_pat, probe->name, 0, NULL, 0) != 0)
&& probe_pat->exec (probe->name, 0, NULL, 0) != 0)
continue;
bound.objfile = objfile;
@ -339,7 +339,6 @@ collect_probes (char *objname, char *provider, char *probe_name,
}
}
do_cleanups (cleanup_temps);
discard_cleanups (cleanup);
return result;
}

View File

@ -34,6 +34,7 @@
#include "filenames.h"
#include "fnmatch.h"
#include "gdb_regex.h"
#include "common/gdb_optional.h"
struct skiplist_entry
{
@ -57,10 +58,7 @@ struct skiplist_entry
char *function;
/* If this is a function regexp, the compiled form. */
regex_t compiled_function_regexp;
/* Non-zero if the function regexp has been compiled. */
int compiled_function_regexp_is_valid;
gdb::optional<compiled_regex> compiled_function_regexp;
int enabled;
@ -112,8 +110,6 @@ free_skiplist_entry (struct skiplist_entry *e)
{
xfree (e->file);
xfree (e->function);
if (e->function_is_regexp && e->compiled_function_regexp_is_valid)
regfree (&e->compiled_function_regexp);
xfree (e);
}
@ -202,7 +198,6 @@ skip_function_command (char *arg, int from_tty)
static void
compile_skip_regexp (struct skiplist_entry *e, const char *message)
{
int code;
int flags = REG_NOSUB;
#ifdef REG_EXTENDED
@ -210,16 +205,7 @@ compile_skip_regexp (struct skiplist_entry *e, const char *message)
#endif
gdb_assert (e->function_is_regexp && e->function != NULL);
code = regcomp (&e->compiled_function_regexp, e->function, flags);
if (code != 0)
{
char *err = get_regcomp_error (code, &e->compiled_function_regexp);
make_cleanup (xfree, err);
error (_("%s: %s"), message, err);
}
e->compiled_function_regexp_is_valid = 1;
e->compiled_function_regexp.emplace (e->function, flags, message);
}
/* Process "skip ..." that does not match "skip file" or "skip function". */
@ -601,8 +587,8 @@ static int
skip_rfunction_p (struct skiplist_entry *e, const char *function_name)
{
gdb_assert (e->function != NULL && e->function_is_regexp
&& e->compiled_function_regexp_is_valid);
return (regexec (&e->compiled_function_regexp, function_name, 0, NULL, 0)
&& e->compiled_function_regexp);
return (e->compiled_function_regexp->exec (function_name, 0, NULL, 0)
== 0);
}

View File

@ -62,6 +62,7 @@
#include "parser-defs.h"
#include "completer.h"
#include "progspace-and-thread.h"
#include "common/gdb_optional.h"
/* Forward declarations for local functions. */
@ -4299,9 +4300,7 @@ search_symbols (const char *regexp, enum search_domain kind,
struct symbol_search *found;
struct symbol_search *tail;
int nfound;
/* This is true if PREG contains valid data, false otherwise. */
bool preg_p;
regex_t preg;
gdb::optional<compiled_regex> preg;
/* OLD_CHAIN .. RETVAL_CHAIN is always freed, RETVAL_CHAIN .. current
CLEANUP_CHAIN is freed only in the case of an error. */
@ -4316,7 +4315,6 @@ search_symbols (const char *regexp, enum search_domain kind,
ourtype4 = types4[kind];
*matches = NULL;
preg_p = false;
if (regexp != NULL)
{
@ -4355,18 +4353,9 @@ search_symbols (const char *regexp, enum search_domain kind,
}
}
errcode = regcomp (&preg, regexp,
REG_NOSUB | (case_sensitivity == case_sensitive_off
? REG_ICASE : 0));
if (errcode != 0)
{
char *err = get_regcomp_error (errcode, &preg);
make_cleanup (xfree, err);
error (_("Invalid regexp (%s): %s"), err, regexp);
}
preg_p = true;
make_regfree_cleanup (&preg);
int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
? REG_ICASE : 0);
preg.emplace (regexp, cflags, _("Invalid regexp"));
}
/* Search through the partial symtabs *first* for all symbols
@ -4379,8 +4368,8 @@ search_symbols (const char *regexp, enum search_domain kind,
},
[&] (const char *symname)
{
return (!preg_p || regexec (&preg, symname,
0, NULL, 0) == 0);
return (!preg || preg->exec (symname,
0, NULL, 0) == 0);
},
NULL,
kind);
@ -4415,9 +4404,9 @@ search_symbols (const char *regexp, enum search_domain kind,
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (!preg_p
|| regexec (&preg, MSYMBOL_NATURAL_NAME (msymbol), 0,
NULL, 0) == 0)
if (!preg
|| preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
NULL, 0) == 0)
{
/* Note: An important side-effect of these lookup functions
is to expand the symbol table if msymbol is found, for the
@ -4459,9 +4448,9 @@ search_symbols (const char *regexp, enum search_domain kind,
files, nfiles, 1))
&& file_matches (symtab_to_fullname (real_symtab),
files, nfiles, 0)))
&& ((!preg_p
|| regexec (&preg, SYMBOL_NATURAL_NAME (sym), 0,
NULL, 0) == 0)
&& ((!preg
|| preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
NULL, 0) == 0)
&& ((kind == VARIABLES_DOMAIN
&& SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_UNRESOLVED
@ -4517,9 +4506,8 @@ search_symbols (const char *regexp, enum search_domain kind,
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (!preg_p
|| regexec (&preg, MSYMBOL_NATURAL_NAME (msymbol), 0,
NULL, 0) == 0)
if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
NULL, 0) == 0)
{
/* For functions we can do a quick check of whether the
symbol might be found via find_pc_symtab. */

View File

@ -1038,58 +1038,6 @@ make_hex_string (const gdb_byte *data, size_t length)
/* A cleanup function that calls regfree. */
static void
do_regfree_cleanup (void *r)
{
regfree ((regex_t *) r);
}
/* Create a new cleanup that frees the compiled regular expression R. */
struct cleanup *
make_regfree_cleanup (regex_t *r)
{
return make_cleanup (do_regfree_cleanup, r);
}
/* Return an xmalloc'd error message resulting from a regular
expression compilation failure. */
char *
get_regcomp_error (int code, regex_t *rx)
{
size_t length = regerror (code, rx, NULL, 0);
char *result = (char *) xmalloc (length);
regerror (code, rx, result, length);
return result;
}
/* Compile a regexp and throw an exception on error. This returns a
cleanup to free the resulting pattern on success. RX must not be
NULL. */
struct cleanup *
compile_rx_or_error (regex_t *pattern, const char *rx, const char *message)
{
int code;
gdb_assert (rx != NULL);
code = regcomp (pattern, rx, REG_NOSUB);
if (code != 0)
{
char *err = get_regcomp_error (code, pattern);
make_cleanup (xfree, err);
error (("%s: %s"), message, err);
}
return make_regfree_cleanup (pattern);
}
/* A cleanup that simply calls ui_unregister_input_event_handler. */
static void