* [RFA 0/2] C++-ify some breakpoint subclasses a bit more
@ 2017-06-04 22:54 Tom Tromey
2017-06-04 22:54 ` [RFA 1/2] C++-ify break-catch-sig Tom Tromey
2017-06-04 22:54 ` [RFA 2/2] C++-ify break-catch-throw Tom Tromey
0 siblings, 2 replies; 17+ messages in thread
From: Tom Tromey @ 2017-06-04 22:54 UTC (permalink / raw)
To: gdb-patches
This short series builds on Simon Marchi's recent C++-ification patch.
It updates a couple of breakpoint subclasses to be more C++-ish, using
string and vector rather than manual memory management and VEC.
Regression tested on the buildbot.
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFA 1/2] C++-ify break-catch-sig
2017-06-04 22:54 [RFA 0/2] C++-ify some breakpoint subclasses a bit more Tom Tromey
@ 2017-06-04 22:54 ` Tom Tromey
2017-06-05 8:43 ` Simon Marchi
2017-06-04 22:54 ` [RFA 2/2] C++-ify break-catch-throw Tom Tromey
1 sibling, 1 reply; 17+ messages in thread
From: Tom Tromey @ 2017-06-04 22:54 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This changes signal_catchpoint to be more of a C++ class, using
std::vector and updating the users.
gdb/ChangeLog
2017-06-04 Tom Tromey <tom@tromey.com>
* break-catch-sig.c (gdb_signal_type): Remove typedef.
(struct signal_catchpoint) <signals_to_be_caught>: Now a
std::vector.
(~signal_catchpoint, signal_catchpoint_insert_location)
(signal_catchpoint_remove_location)
(signal_catchpoint_breakpoint_hit, signal_catchpoint_print_one)
(signal_catchpoint_print_mention)
(signal_catchpoint_print_recreate)
(signal_catchpoint_explains_signal): Update.
(create_signal_catchpoint): Change type of "filter".
(catch_signal_split_args): Return a std::vector.
(catch_signal_command): Update.
---
gdb/ChangeLog | 15 ++++++
gdb/break-catch-sig.c | 127 +++++++++++++++++++-------------------------------
2 files changed, 63 insertions(+), 79 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7fe5334..b89b47d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,18 @@
+2017-06-04 Tom Tromey <tom@tromey.com>
+
+ * break-catch-sig.c (gdb_signal_type): Remove typedef.
+ (struct signal_catchpoint) <signals_to_be_caught>: Now a
+ std::vector.
+ (~signal_catchpoint, signal_catchpoint_insert_location)
+ (signal_catchpoint_remove_location)
+ (signal_catchpoint_breakpoint_hit, signal_catchpoint_print_one)
+ (signal_catchpoint_print_mention)
+ (signal_catchpoint_print_recreate)
+ (signal_catchpoint_explains_signal): Update.
+ (create_signal_catchpoint): Change type of "filter".
+ (catch_signal_split_args): Return a std::vector.
+ (catch_signal_command): Update.
+
2017-06-03 Simon Marchi <simon.marchi@ericsson.com>
* x86-linux-nat.c (struct arch_lwp_info): Remove.
diff --git a/gdb/break-catch-sig.c b/gdb/break-catch-sig.c
index 3eede93..8512bd8 100644
--- a/gdb/break-catch-sig.c
+++ b/gdb/break-catch-sig.c
@@ -33,10 +33,6 @@
#define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
-typedef enum gdb_signal gdb_signal_type;
-
-DEF_VEC_I (gdb_signal_type);
-
/* An instance of this type is used to represent a signal catchpoint.
A breakpoint is really of this type iff its ops pointer points to
SIGNAL_CATCHPOINT_OPS. */
@@ -46,14 +42,14 @@ struct signal_catchpoint : public breakpoint
~signal_catchpoint () override;
/* Signal numbers used for the 'catch signal' feature. If no signal
- has been specified for filtering, its value is NULL. Otherwise,
+ has been specified for filtering, it is empty. Otherwise,
it holds a list of all signals to be caught. */
- VEC (gdb_signal_type) *signals_to_be_caught;
+ std::vector<gdb_signal> signals_to_be_caught;
- /* If SIGNALS_TO_BE_CAUGHT is NULL, then all "ordinary" signals are
+ /* If SIGNALS_TO_BE_CAUGHT is empty, then all "ordinary" signals are
caught. If CATCH_ALL is non-zero, then internal signals are
- caught as well. If SIGNALS_TO_BE_CAUGHT is non-NULL, then this
+ caught as well. If SIGNALS_TO_BE_CAUGHT is not empty, then this
field is ignored. */
int catch_all;
@@ -89,7 +85,6 @@ signal_to_name_or_int (enum gdb_signal sig)
signal_catchpoint::~signal_catchpoint ()
{
- VEC_free (gdb_signal_type, this->signals_to_be_caught);
}
/* Implement the "insert_location" breakpoint_ops method for signal
@@ -99,20 +94,17 @@ static int
signal_catchpoint_insert_location (struct bp_location *bl)
{
struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
- int i;
- if (c->signals_to_be_caught != NULL)
+ if (!c->signals_to_be_caught.empty ())
{
- gdb_signal_type iter;
+ gdb_signal iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
+ for (auto iter : c->signals_to_be_caught)
++signal_catch_counts[iter];
}
else
{
- for (i = 0; i < GDB_SIGNAL_LAST; ++i)
+ for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
{
if (c->catch_all || !INTERNAL_SIGNAL (i))
++signal_catch_counts[i];
@@ -132,15 +124,12 @@ signal_catchpoint_remove_location (struct bp_location *bl,
enum remove_bp_reason reason)
{
struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
- int i;
- if (c->signals_to_be_caught != NULL)
+ if (!c->signals_to_be_caught.empty ())
{
- gdb_signal_type iter;
+ gdb_signal iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
+ for (auto iter : c->signals_to_be_caught)
{
gdb_assert (signal_catch_counts[iter] > 0);
--signal_catch_counts[iter];
@@ -148,7 +137,7 @@ signal_catchpoint_remove_location (struct bp_location *bl,
}
else
{
- for (i = 0; i < GDB_SIGNAL_LAST; ++i)
+ for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
{
if (c->catch_all || !INTERNAL_SIGNAL (i))
{
@@ -174,7 +163,7 @@ signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
{
const struct signal_catchpoint *c
= (const struct signal_catchpoint *) bl->owner;
- gdb_signal_type signal_number;
+ gdb_signal signal_number;
if (ws->kind != TARGET_WAITKIND_STOPPED)
return 0;
@@ -184,18 +173,14 @@ signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
/* If we are catching specific signals in this breakpoint, then we
must guarantee that the called signal is the same signal we are
catching. */
- if (c->signals_to_be_caught)
+ if (!c->signals_to_be_caught.empty ())
{
- int i;
- gdb_signal_type iter;
+ gdb_signal iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
+ for (auto iter : c->signals_to_be_caught)
if (signal_number == iter)
return 1;
/* Not the same. */
- gdb_assert (!iter);
return 0;
}
else
@@ -246,26 +231,25 @@ signal_catchpoint_print_one (struct breakpoint *b,
uiout->field_skip ("addr");
annotate_field (5);
- if (c->signals_to_be_caught
- && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
+ if (!c->signals_to_be_caught.empty ())
uiout->text ("signals \"");
else
uiout->text ("signal \"");
- if (c->signals_to_be_caught)
+ if (!c->signals_to_be_caught.empty ())
{
- int i;
- gdb_signal_type iter;
+ gdb_signal iter;
std::string text;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
+ bool first = true;
+ for (auto iter : c->signals_to_be_caught)
{
const char *name = signal_to_name_or_int (iter);
- if (i > 0)
+ if (!first)
text += " ";
+ first = false;
+
text += name;
}
uiout->field_string ("what", text.c_str ());
@@ -287,19 +271,16 @@ signal_catchpoint_print_mention (struct breakpoint *b)
{
struct signal_catchpoint *c = (struct signal_catchpoint *) b;
- if (c->signals_to_be_caught)
+ if (!c->signals_to_be_caught.empty ())
{
- int i;
- gdb_signal_type iter;
+ gdb_signal iter;
- if (VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
+ if (c->signals_to_be_caught.size () > 1)
printf_filtered (_("Catchpoint %d (signals"), b->number);
else
printf_filtered (_("Catchpoint %d (signal"), b->number);
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
+ for (auto iter : c->signals_to_be_caught)
{
const char *name = signal_to_name_or_int (iter);
@@ -323,14 +304,11 @@ signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
fprintf_unfiltered (fp, "catch signal");
- if (c->signals_to_be_caught)
+ if (!c->signals_to_be_caught.empty ())
{
- int i;
- gdb_signal_type iter;
+ gdb_signal iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
+ for (auto iter : c->signals_to_be_caught)
fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
}
else if (c->catch_all)
@@ -355,7 +333,7 @@ signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
then internal signals like SIGTRAP are not caught. */
static void
-create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
+create_signal_catchpoint (int tempflag, std::vector<gdb_signal> &&filter,
int catch_all)
{
struct signal_catchpoint *c;
@@ -363,7 +341,7 @@ create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
c = new signal_catchpoint ();
init_catchpoint (c, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
- c->signals_to_be_caught = filter;
+ c->signals_to_be_caught = std::move (filter);
c->catch_all = catch_all;
install_breakpoint (0, c, 1);
@@ -373,57 +351,50 @@ create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
/* Splits the argument using space as delimiter. Returns an xmalloc'd
filter list, or NULL if no filtering is required. */
-static VEC (gdb_signal_type) *
+static std::vector<gdb_signal>
catch_signal_split_args (char *arg, int *catch_all)
{
- VEC (gdb_signal_type) *result = NULL;
- struct cleanup *cleanup = make_cleanup (VEC_cleanup (gdb_signal_type),
- &result);
+ std::vector<gdb_signal> result;
int first = 1;
while (*arg != '\0')
{
int num;
- gdb_signal_type signal_number;
- char *one_arg, *endptr;
- struct cleanup *inner_cleanup;
+ gdb_signal signal_number;
+ char *endptr;
- one_arg = extract_arg (&arg);
+ gdb::unique_xmalloc_ptr<char> one_arg (extract_arg (&arg));
if (one_arg == NULL)
break;
- inner_cleanup = make_cleanup (xfree, one_arg);
/* Check for the special flag "all". */
- if (strcmp (one_arg, "all") == 0)
+ if (strcmp (one_arg.get (), "all") == 0)
{
arg = skip_spaces (arg);
if (*arg != '\0' || !first)
error (_("'all' cannot be caught with other signals"));
*catch_all = 1;
- gdb_assert (result == NULL);
- do_cleanups (inner_cleanup);
- discard_cleanups (cleanup);
- return NULL;
+ gdb_assert (result.empty ());
+ return result;
}
first = 0;
/* Check if the user provided a signal name or a number. */
- num = (int) strtol (one_arg, &endptr, 0);
+ num = (int) strtol (one_arg.get (), &endptr, 0);
if (*endptr == '\0')
signal_number = gdb_signal_from_command (num);
else
{
- signal_number = gdb_signal_from_name (one_arg);
+ signal_number = gdb_signal_from_name (one_arg.get ());
if (signal_number == GDB_SIGNAL_UNKNOWN)
- error (_("Unknown signal name '%s'."), one_arg);
+ error (_("Unknown signal name '%s'."), one_arg.get ());
}
- VEC_safe_push (gdb_signal_type, result, signal_number);
- do_cleanups (inner_cleanup);
+ result.push_back (signal_number);
}
- discard_cleanups (cleanup);
+ result.shrink_to_fit ();
return result;
}
@@ -434,7 +405,7 @@ catch_signal_command (char *arg, int from_tty,
struct cmd_list_element *command)
{
int tempflag, catch_all = 0;
- VEC (gdb_signal_type) *filter;
+ std::vector<gdb_signal> filter;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
@@ -448,10 +419,8 @@ catch_signal_command (char *arg, int from_tty,
if (arg != NULL)
filter = catch_signal_split_args (arg, &catch_all);
- else
- filter = NULL;
- create_signal_catchpoint (tempflag, filter, catch_all);
+ create_signal_catchpoint (tempflag, std::move (filter), catch_all);
}
static void
--
2.9.3
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFA 2/2] C++-ify break-catch-throw
2017-06-04 22:54 [RFA 0/2] C++-ify some breakpoint subclasses a bit more Tom Tromey
2017-06-04 22:54 ` [RFA 1/2] C++-ify break-catch-sig Tom Tromey
@ 2017-06-04 22:54 ` Tom Tromey
2017-06-05 8:54 ` Simon Marchi
2017-06-05 10:21 ` Pedro Alves
1 sibling, 2 replies; 17+ messages in thread
From: Tom Tromey @ 2017-06-04 22:54 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This changes exception_catchpoint to be more of a C++ class, using
std::string and std::vector, and updating the users.
gdb/ChangeLog
2017-06-04 Tom Tromey <tom@tromey.com>
* break-catch-throw.c (struct exception_catchpoint)
<exception_rx>: Now a std::string.
<pattern>: Now a unique_ptr.
(~exception_catchpoint, check_status_exception_catchpoint)
(print_one_detail_exception_catchpoint): Update.
(handle_gnu_v3_exceptions): Change type of except_rx.
(extract_exception_regexp): Return a std::string.
(catch_exception_command_1): Update.
---
gdb/ChangeLog | 11 +++++++++++
gdb/break-catch-throw.c | 49 +++++++++++++++++++++----------------------------
2 files changed, 32 insertions(+), 28 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b89b47d..7be1267 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,16 @@
2017-06-04 Tom Tromey <tom@tromey.com>
+ * break-catch-throw.c (struct exception_catchpoint)
+ <exception_rx>: Now a std::string.
+ <pattern>: Now a unique_ptr.
+ (~exception_catchpoint, check_status_exception_catchpoint)
+ (print_one_detail_exception_catchpoint): Update.
+ (handle_gnu_v3_exceptions): Change type of except_rx.
+ (extract_exception_regexp): Return a std::string.
+ (catch_exception_command_1): Update.
+
+2017-06-04 Tom Tromey <tom@tromey.com>
+
* break-catch-sig.c (gdb_signal_type): Remove typedef.
(struct signal_catchpoint) <signals_to_be_caught>: Now a
std::vector.
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 7731c5e..5e88ad5 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -82,15 +82,15 @@ struct exception_catchpoint : public breakpoint
enum exception_event_kind kind;
- /* If non-NULL, an xmalloc'd string holding the source form of the
- regular expression to match against. */
+ /* If not empty, a string holding the source form of the regular
+ expression to match against. */
- char *exception_rx;
+ std::string exception_rx;
- /* If non-NULL, an xmalloc'd, compiled regular expression which is
+ /* If non-NULL, a compiled regular expression which is
used to determine which exceptions to stop on. */
- regex_t *pattern;
+ std::unique_ptr<regex_t> pattern;
};
\f
@@ -144,9 +144,8 @@ classify_exception_breakpoint (struct breakpoint *b)
exception_catchpoint::~exception_catchpoint ()
{
- xfree (this->exception_rx);
if (this->pattern != NULL)
- regfree (this->pattern);
+ regfree (this->pattern.get ());
}
/* Implement the 'check_status' method. */
@@ -185,7 +184,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 (regexec (self->pattern.get (), type_name.c_str (), 0, NULL, 0) != 0)
bs->stop = 0;
}
}
@@ -321,10 +320,10 @@ print_one_detail_exception_catchpoint (const struct breakpoint *b,
const struct exception_catchpoint *cp
= (const struct exception_catchpoint *) b;
- if (cp->exception_rx != NULL)
+ if (!cp->exception_rx.empty ())
{
uiout->text (_("\tmatching: "));
- uiout->field_string ("regexp", cp->exception_rx);
+ uiout->field_string ("regexp", cp->exception_rx.c_str ());
uiout->text ("\n");
}
}
@@ -373,18 +372,17 @@ print_recreate_exception_catchpoint (struct breakpoint *b,
}
static void
-handle_gnu_v3_exceptions (int tempflag, char *except_rx,
+handle_gnu_v3_exceptions (int tempflag, std::string &&except_rx,
const char *cond_string,
enum exception_event_kind ex_event, int from_tty)
{
- regex_t *pattern = NULL;
+ std::unique_ptr<regex_t> pattern;
- if (except_rx != NULL)
+ if (!except_rx.empty ())
{
- pattern = XNEW (regex_t);
- make_cleanup (xfree, pattern);
+ pattern.reset (new regex_t);
- compile_rx_or_error (pattern, except_rx,
+ compile_rx_or_error (pattern.get (), except_rx.c_str (),
_("invalid type-matching regexp"));
}
@@ -396,8 +394,8 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx,
the right thing. */
cp->type = bp_breakpoint;
cp->kind = ex_event;
- cp->exception_rx = except_rx;
- cp->pattern = pattern;
+ cp->exception_rx = std::move (except_rx);
+ cp->pattern = std::move (pattern);
re_set_exception_catchpoint (cp.get ());
@@ -415,7 +413,7 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx,
STRING is updated to point to the "if" token, if it exists, or to
the end of the string. */
-static char *
+static std::string
extract_exception_regexp (const char **string)
{
const char *start;
@@ -440,8 +438,8 @@ extract_exception_regexp (const char **string)
*string = last;
if (last_space > start)
- return savestring (start, last_space - start);
- return NULL;
+ return std::string (start, last_space - start);
+ return std::string ();
}
/* Deal with "catch catch", "catch throw", and "catch rethrow"
@@ -452,17 +450,14 @@ catch_exception_command_1 (enum exception_event_kind ex_event,
char *arg_entry,
int tempflag, int from_tty)
{
- char *except_rx;
const char *cond_string = NULL;
- struct cleanup *cleanup;
const char *arg = arg_entry;
if (!arg)
arg = "";
arg = skip_spaces_const (arg);
- except_rx = extract_exception_regexp (&arg);
- cleanup = make_cleanup (xfree, except_rx);
+ std::string except_rx = extract_exception_regexp (&arg);
cond_string = ep_parse_optional_if_clause (&arg);
@@ -474,10 +469,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event,
&& ex_event != EX_EVENT_RETHROW)
error (_("Unsupported or unknown exception event; cannot catch it"));
- handle_gnu_v3_exceptions (tempflag, except_rx, cond_string,
+ handle_gnu_v3_exceptions (tempflag, std::move (except_rx), cond_string,
ex_event, from_tty);
-
- discard_cleanups (cleanup);
}
/* Implementation of "catch catch" command. */
--
2.9.3
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 1/2] C++-ify break-catch-sig
2017-06-04 22:54 ` [RFA 1/2] C++-ify break-catch-sig Tom Tromey
@ 2017-06-05 8:43 ` Simon Marchi
2017-06-05 13:13 ` Tom Tromey
2017-06-05 13:53 ` Tom Tromey
0 siblings, 2 replies; 17+ messages in thread
From: Simon Marchi @ 2017-06-05 8:43 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 2017-06-05 00:53, Tom Tromey wrote:
> This changes signal_catchpoint to be more of a C++ class, using
> std::vector and updating the users.
>
> gdb/ChangeLog
> 2017-06-04 Tom Tromey <tom@tromey.com>
>
> * break-catch-sig.c (gdb_signal_type): Remove typedef.
> (struct signal_catchpoint) <signals_to_be_caught>: Now a
> std::vector.
> (~signal_catchpoint, signal_catchpoint_insert_location)
> (signal_catchpoint_remove_location)
> (signal_catchpoint_breakpoint_hit, signal_catchpoint_print_one)
> (signal_catchpoint_print_mention)
> (signal_catchpoint_print_recreate)
> (signal_catchpoint_explains_signal): Update.
> (create_signal_catchpoint): Change type of "filter".
> (catch_signal_split_args): Return a std::vector.
> (catch_signal_command): Update.
> ---
Hi Tom,
Thanks for doing this. The patch looks good in general. I'd suggest
doing these in the same patch:
- make the catch_all field/parameter/variable a bool,
- remove the destructor, since it's now empty.
> @@ -99,20 +94,17 @@ static int
> signal_catchpoint_insert_location (struct bp_location *bl)
> {
> struct signal_catchpoint *c = (struct signal_catchpoint *)
> bl->owner;
> - int i;
>
> - if (c->signals_to_be_caught != NULL)
> + if (!c->signals_to_be_caught.empty ())
> {
> - gdb_signal_type iter;
> + gdb_signal iter;
You don't need this declaration...
> - for (i = 0;
> - VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
> - i++)
> + for (auto iter : c->signals_to_be_caught)
...because it's overriden by this one. Although I'd prefer if you used
"gdb_signal" instead of "auto" here. It's not much longer, is more
expressive. There are a few instances of this throughout the patch.
> @@ -246,26 +231,25 @@ signal_catchpoint_print_one (struct breakpoint
> *b,
> uiout->field_skip ("addr");
> annotate_field (5);
>
> - if (c->signals_to_be_caught
> - && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
> + if (!c->signals_to_be_caught.empty ())
I think you changed the behavior of this condition. It should probably
be:
c->signals_to_be_caught.size () > 1
With those comments addressed, the patch is good to me.
Thanks!
Simon
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-04 22:54 ` [RFA 2/2] C++-ify break-catch-throw Tom Tromey
@ 2017-06-05 8:54 ` Simon Marchi
2017-06-05 19:10 ` Tom Tromey
2017-06-05 10:21 ` Pedro Alves
1 sibling, 1 reply; 17+ messages in thread
From: Simon Marchi @ 2017-06-05 8:54 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> --- a/gdb/break-catch-throw.c
> +++ b/gdb/break-catch-throw.c
> @@ -82,15 +82,15 @@ struct exception_catchpoint : public breakpoint
>
> enum exception_event_kind kind;
>
> - /* If non-NULL, an xmalloc'd string holding the source form of the
> - regular expression to match against. */
> + /* If not empty, a string holding the source form of the regular
> + expression to match against. */
>
> - char *exception_rx;
> + std::string exception_rx;
>
> - /* If non-NULL, an xmalloc'd, compiled regular expression which is
> + /* If non-NULL, a compiled regular expression which is
> used to determine which exceptions to stop on. */
>
> - regex_t *pattern;
> + std::unique_ptr<regex_t> pattern;
From what I understand, we were freeing the regex with regfree, but we
weren't freeing the regex_t object, which is allocated separately, is
that right? Or what is freed in handle_gnu_v3_exceptions by the
cleanup, and then referenced later? Either way your code LGTM.
Simon
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-04 22:54 ` [RFA 2/2] C++-ify break-catch-throw Tom Tromey
2017-06-05 8:54 ` Simon Marchi
@ 2017-06-05 10:21 ` Pedro Alves
2017-06-05 10:33 ` Pedro Alves
1 sibling, 1 reply; 17+ messages in thread
From: Pedro Alves @ 2017-06-05 10:21 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 06/04/2017 11:53 PM, Tom Tromey wrote:
> @@ -452,17 +450,14 @@ catch_exception_command_1 (enum exception_event_kind ex_event,
> char *arg_entry,
> int tempflag, int from_tty)
> {
> - char *except_rx;
> const char *cond_string = NULL;
> - struct cleanup *cleanup;
> const char *arg = arg_entry;
>
> if (!arg)
> arg = "";
> arg = skip_spaces_const (arg);
>
> - except_rx = extract_exception_regexp (&arg);
> - cleanup = make_cleanup (xfree, except_rx);
> + std::string except_rx = extract_exception_regexp (&arg);
>
> cond_string = ep_parse_optional_if_clause (&arg);
>
> @@ -474,10 +469,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event,
> && ex_event != EX_EVENT_RETHROW)
> error (_("Unsupported or unknown exception event; cannot catch it"));
>
> - handle_gnu_v3_exceptions (tempflag, except_rx, cond_string,
> + handle_gnu_v3_exceptions (tempflag, std::move (except_rx), cond_string,
> ex_event, from_tty);
> -
> - discard_cleanups (cleanup);
> }
Something looks suspicious to me -- compile_rx_or_error returns with
an installed cleanup that calls regfree, and handle_gnu_v3_exceptions
leaves it installed too.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-05 10:21 ` Pedro Alves
@ 2017-06-05 10:33 ` Pedro Alves
2017-06-05 10:36 ` Pedro Alves
0 siblings, 1 reply; 17+ messages in thread
From: Pedro Alves @ 2017-06-05 10:33 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 06/05/2017 11:21 AM, Pedro Alves wrote:
> On 06/04/2017 11:53 PM, Tom Tromey wrote:
>> @@ -452,17 +450,14 @@ catch_exception_command_1 (enum exception_event_kind ex_event,
>> char *arg_entry,
>> int tempflag, int from_tty)
>> {
>> - char *except_rx;
>> const char *cond_string = NULL;
>> - struct cleanup *cleanup;
>> const char *arg = arg_entry;
>>
>> if (!arg)
>> arg = "";
>> arg = skip_spaces_const (arg);
>>
>> - except_rx = extract_exception_regexp (&arg);
>> - cleanup = make_cleanup (xfree, except_rx);
>> + std::string except_rx = extract_exception_regexp (&arg);
>>
>> cond_string = ep_parse_optional_if_clause (&arg);
>>
>> @@ -474,10 +469,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event,
>> && ex_event != EX_EVENT_RETHROW)
>> error (_("Unsupported or unknown exception event; cannot catch it"));
>>
>> - handle_gnu_v3_exceptions (tempflag, except_rx, cond_string,
>> + handle_gnu_v3_exceptions (tempflag, std::move (except_rx), cond_string,
>> ex_event, from_tty);
>> -
>> - discard_cleanups (cleanup);
>> }
>
> Something looks suspicious to me -- compile_rx_or_error returns with
> an installed cleanup that calls regfree, and handle_gnu_v3_exceptions
> leaves it installed too.
Maybe the cleanest would be to add a wrapper around regex_t,
and replace compile_rx_or_error with a ctor that throws,
like:
class gdb_regex
{
public:
// replaces old compile_rx_or_error
gdb_regex (const char *rx, const char *message)
{
gdb_assert (rx != NULL);
int code = regcomp (&m_pattern, rx, REG_NOSUB);
if (code != 0)
{
gdb::unique_xmalloc_ptr<char> err
= get_regcomp_error (code, &m_pattern);
error (("%s: %s"), message, err.get ());
}
}
~gdb_regex ()
{
regfree (&m_pattern);
}
// add convenience methods as needed.
private:
regex_t m_pattern;
};
and use it throughout.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-05 10:33 ` Pedro Alves
@ 2017-06-05 10:36 ` Pedro Alves
2017-06-05 12:29 ` Pedro Alves
0 siblings, 1 reply; 17+ messages in thread
From: Pedro Alves @ 2017-06-05 10:36 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 06/05/2017 11:33 AM, Pedro Alves wrote:
> class gdb_regex
> {
> public:
> // replaces old compile_rx_or_error
> gdb_regex (const char *rx, const char *message)
> {
Maybe call it "compiled_regex" instead, since you wouldn't
be able to end up with a not-compiled-yet regex with this.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-05 10:36 ` Pedro Alves
@ 2017-06-05 12:29 ` Pedro Alves
2017-06-05 12:32 ` Pedro Alves
2017-06-05 19:27 ` Tom Tromey
0 siblings, 2 replies; 17+ messages in thread
From: Pedro Alves @ 2017-06-05 12:29 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 06/05/2017 11:36 AM, Pedro Alves wrote:
> On 06/05/2017 11:33 AM, Pedro Alves wrote:
>> class gdb_regex
>> {
>> public:
>> // replaces old compile_rx_or_error
>> gdb_regex (const char *rx, const char *message)
>> {
>
> Maybe call it "compiled_regex" instead, since you wouldn't
> be able to end up with a not-compiled-yet regex with this.
>
So something like this. Builds and gdb starts, but I have
not regtested it.
In a couple places, this either forces moving the regex object
to the heap, or to wrap it in gdb::optional. In the cases
where we already have to keep the regex string around,
it ends up being not maximally efficient memory-wise, but I don't
think it really matters. We're considering std::string for
those same strings, which grows the structs more than that, anyway
(for size/capacity).
For linux-tdep.cmapping_is_anonymous_p, I was first considering
std::aligned_storage, but switched back to gdb::optional before posting,
because std::aligned_storage complicates the code a little bit (I mean, forces
readers to learn about std::aligned_storage while here the redundant
"has value" variable that gdb::optional has internally doesn't really
matter. We could move the mapping_regexes struct to the heap too, since is
a one-shot initialization. (I see now that I left the "tristate" comment behind.)
I didn't use "compiled_regex" for struct name, simply because "gdb_regex.h"
already existed. But I'd still consider renaming it.
WDYT?
From 26a9200f3b8f94f24b4c026413ffd7968fd3ea01 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Mon, 5 Jun 2017 12:48:46 +0100
Subject: [PATCH] gdb_regex
---
gdb/Makefile.in | 2 ++
gdb/ada-lang.c | 30 ++++++----------
gdb/break-catch-throw.c | 21 +++++------
gdb/breakpoint.c | 19 +++-------
gdb/cli/cli-cmds.c | 21 ++---------
gdb/cli/cli-decode.c | 11 +++---
gdb/cli/cli-decode.h | 5 ++-
gdb/gdb_regex.h | 26 +++++++++++---
gdb/linux-tdep.c | 93 +++++++++++++++++++++++++------------------------
gdb/probe.c | 19 +++++-----
gdb/skip.c | 24 +++----------
gdb/symtab.c | 42 ++++++++--------------
gdb/utils.c | 52 ---------------------------
13 files changed, 135 insertions(+), 230 deletions(-)
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8be73ba..2156438 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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 \
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index f90907a..e338cd1 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13219,14 +13219,14 @@ 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 (gdb_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 +13253,7 @@ 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 (gdb_regex *preg, struct frame_info *frame,
VEC(ada_exc_info) **exceptions)
{
const struct block *block = get_frame_block (frame, 0);
@@ -13290,10 +13290,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, gdb_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 +13316,7 @@ 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 (gdb_regex *preg, VEC(ada_exc_info) **exceptions)
{
struct objfile *objfile;
struct compunit_symtab *s;
@@ -13364,7 +13364,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 (gdb_regex *preg)
{
VEC(ada_exc_info) *result = NULL;
struct cleanup *old_chain
@@ -13417,19 +13417,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)
- old_chain = compile_rx_or_error (®, regexp,
- _("invalid regular expression"));
+ if (regexp == NULL)
+ return ada_exceptions_list_1 (NULL);
- result = ada_exceptions_list_1 (regexp != NULL ? ® : NULL);
-
- if (old_chain != NULL)
- do_cleanups (old_chain);
- return result;
+ gdb_regex reg (regexp, REG_NOSUB, _("invalid regular expression"));
+ return ada_exceptions_list_1 (®);
}
/* Implement the "info exceptions" command. */
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 7731c5e..49d5180 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -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<gdb_regex> pattern;
};
\f
@@ -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<gdb_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 gdb_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 ());
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0dc9841..b78cf2b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -8282,13 +8282,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<gdb_regex> compiled;
};
solib_catchpoint::~solib_catchpoint ()
{
- if (this->regex)
- regfree (&this->compiled);
xfree (this->regex);
}
@@ -8356,7 +8354,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;
}
}
@@ -8370,7 +8368,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;
}
}
@@ -8486,16 +8484,7 @@ 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 gdb_regex (arg, REG_NOSUB, _("Invalid regexp")));
c->regex = xstrdup (arg);
}
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 2a5b128..3aedecd 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -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;
+ gdb_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.
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index d386d02..87ac0d5 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -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)
+ gdb_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);
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index 66159fd..b8f2f7c 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -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 *);
+ gdb_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
diff --git a/gdb/gdb_regex.h b/gdb/gdb_regex.h
index 0be26ef..2b0a5a0 100644
--- a/gdb/gdb_regex.h
+++ b/gdb/gdb_regex.h
@@ -27,10 +27,26 @@
# 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. */
+
+class gdb_regex
+{
+public:
+ /* Compile a regexp and throw an exception on error, including
+ MESSAGE. REGEX and MESSAGE must not be NULL. */
+ gdb_regex (const char *regex, int cflags,
+ const char *message);
+ ~gdb_regex ();
+
+ /* Wrapper around ::regexec. */
+ int exec (const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+
+ /* Wrapper around ::re_search. */
+ int search (const char *string, int size,
+ int startpos, int range, struct re_registers *regs);
+
+private:
+ regex_t m_pattern;
+};
#endif /* not GDB_REGEX_H */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 016aadf..f424947 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -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,47 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
}
}
+struct mapping_regexes
+{
+ mapping_regexes ()
+ : dev_zero
+ ("^/dev/zero\\( (deleted)\\)\\?$", REG_NOSUB,
+ _("Could not compile regex to match /dev/zero filename")),
+ shmem_file
+ ("^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$", REG_NOSUB,
+ _("Could not compile regex to match shmem filenames")),
+ file_deleted
+ (" (deleted)$", REG_NOSUB,
+ _("Could not compile regex to match '<file> (deleted)'"))
+ {}
+
+ /* 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. */
+ gdb_regex dev_zero;
+
+ /* 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. */
+ gdb_regex shmem_file;
+
+ /* 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. */
+ gdb_regex 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 +548,13 @@ 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;
+ /* Like gdb::optional, but tristate. */
static int init_regex_p = 0;
+ static gdb::optional<mapping_regexes> regexes;
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;
diff --git a/gdb/probe.c b/gdb/probe.c
index e65e031..c8b92f3 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -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<gdb_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;
}
diff --git a/gdb/skip.c b/gdb/skip.c
index 4bd8a9e..65583d8 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -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<gdb_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);
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 22d81fa..1c1eb6c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -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<gdb_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. */
diff --git a/gdb/utils.c b/gdb/utils.c
index b4332f8..88a1789 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1038,58 +1038,6 @@ make_hex_string (const gdb_byte *data, size_t length)
\f
-/* 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
--
2.5.5
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-05 12:29 ` Pedro Alves
@ 2017-06-05 12:32 ` Pedro Alves
2017-06-05 19:27 ` Tom Tromey
1 sibling, 0 replies; 17+ messages in thread
From: Pedro Alves @ 2017-06-05 12:32 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 06/05/2017 01:29 PM, Pedro Alves wrote:
> On 06/05/2017 11:36 AM, Pedro Alves wrote:
>> On 06/05/2017 11:33 AM, Pedro Alves wrote:
>>> class gdb_regex
>>> {
>>> public:
>>> // replaces old compile_rx_or_error
>>> gdb_regex (const char *rx, const char *message)
>>> {
>>
>> Maybe call it "compiled_regex" instead, since you wouldn't
>> be able to end up with a not-compiled-yet regex with this.
>>
>
> So something like this. Builds and gdb starts, but I have
> not regtested it.
>
> In a couple places, this either forces moving the regex object
> to the heap, or to wrap it in gdb::optional. In the cases
> where we already have to keep the regex string around,
> it ends up being not maximally efficient memory-wise, but I don't
> think it really matters. We're considering std::string for
> those same strings, which grows the structs more than that, anyway
> (for size/capacity).
>
> For linux-tdep.cmapping_is_anonymous_p, I was first considering
> std::aligned_storage, but switched back to gdb::optional before posting,
> because std::aligned_storage complicates the code a little bit (I mean, forces
> readers to learn about std::aligned_storage while here the redundant
> "has value" variable that gdb::optional has internally doesn't really
> matter. We could move the mapping_regexes struct to the heap too, since is
> a one-shot initialization. (I see now that I left the "tristate" comment behind.)
>
> I didn't use "compiled_regex" for struct name, simply because "gdb_regex.h"
> already existed. But I'd still consider renaming it.
>
> WDYT?
>
Forgot to "git add" the new file... Trying again.
From 529e26f36ae5ed1f7ee7d375d54843d0b435cf83 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Mon, 5 Jun 2017 12:48:46 +0100
Subject: [PATCH] gdb_regex
---
gdb/Makefile.in | 2 ++
gdb/ada-lang.c | 30 ++++++----------
gdb/break-catch-throw.c | 21 +++++------
gdb/breakpoint.c | 19 +++-------
gdb/cli/cli-cmds.c | 21 ++---------
gdb/cli/cli-decode.c | 11 +++---
gdb/cli/cli-decode.h | 5 ++-
gdb/gdb_regex.c | 59 +++++++++++++++++++++++++++++++
gdb/gdb_regex.h | 26 +++++++++++---
gdb/linux-tdep.c | 93 +++++++++++++++++++++++++------------------------
gdb/probe.c | 19 +++++-----
gdb/skip.c | 24 +++----------
gdb/symtab.c | 42 ++++++++--------------
gdb/utils.c | 52 ---------------------------
14 files changed, 194 insertions(+), 230 deletions(-)
create mode 100644 gdb/gdb_regex.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8be73ba..2156438 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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 \
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index f90907a..e338cd1 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13219,14 +13219,14 @@ 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 (gdb_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 +13253,7 @@ 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 (gdb_regex *preg, struct frame_info *frame,
VEC(ada_exc_info) **exceptions)
{
const struct block *block = get_frame_block (frame, 0);
@@ -13290,10 +13290,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, gdb_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 +13316,7 @@ 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 (gdb_regex *preg, VEC(ada_exc_info) **exceptions)
{
struct objfile *objfile;
struct compunit_symtab *s;
@@ -13364,7 +13364,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 (gdb_regex *preg)
{
VEC(ada_exc_info) *result = NULL;
struct cleanup *old_chain
@@ -13417,19 +13417,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)
- old_chain = compile_rx_or_error (®, regexp,
- _("invalid regular expression"));
+ if (regexp == NULL)
+ return ada_exceptions_list_1 (NULL);
- result = ada_exceptions_list_1 (regexp != NULL ? ® : NULL);
-
- if (old_chain != NULL)
- do_cleanups (old_chain);
- return result;
+ gdb_regex reg (regexp, REG_NOSUB, _("invalid regular expression"));
+ return ada_exceptions_list_1 (®);
}
/* Implement the "info exceptions" command. */
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 7731c5e..49d5180 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -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<gdb_regex> pattern;
};
\f
@@ -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<gdb_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 gdb_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 ());
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0dc9841..b78cf2b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -8282,13 +8282,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<gdb_regex> compiled;
};
solib_catchpoint::~solib_catchpoint ()
{
- if (this->regex)
- regfree (&this->compiled);
xfree (this->regex);
}
@@ -8356,7 +8354,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;
}
}
@@ -8370,7 +8368,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;
}
}
@@ -8486,16 +8484,7 @@ 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 gdb_regex (arg, REG_NOSUB, _("Invalid regexp")));
c->regex = xstrdup (arg);
}
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 2a5b128..3aedecd 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -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;
+ gdb_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.
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index d386d02..87ac0d5 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -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)
+ gdb_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);
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index 66159fd..b8f2f7c 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -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 *);
+ gdb_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
diff --git a/gdb/gdb_regex.c b/gdb/gdb_regex.c
new file mode 100644
index 0000000..06c4666
--- /dev/null
+++ b/gdb/gdb_regex.c
@@ -0,0 +1,59 @@
+/* Portable <regex.h>.
+
+ Copyright (C) 1986-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"
+
+/* See gdb_regex.h. */
+
+gdb_regex::gdb_regex (const char *regex, int cflags,
+ const char *message)
+{
+ gdb_assert (regex != 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 ());
+ }
+}
+
+gdb_regex::~gdb_regex ()
+{
+ regfree (&m_pattern);
+}
+
+int
+gdb_regex::exec (const char *string, size_t nmatch,
+ regmatch_t pmatch[], int eflags)
+{
+ return regexec (&m_pattern, string, nmatch, pmatch, eflags);
+}
+
+int
+gdb_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);
+}
diff --git a/gdb/gdb_regex.h b/gdb/gdb_regex.h
index 0be26ef..2b0a5a0 100644
--- a/gdb/gdb_regex.h
+++ b/gdb/gdb_regex.h
@@ -27,10 +27,26 @@
# 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. */
+
+class gdb_regex
+{
+public:
+ /* Compile a regexp and throw an exception on error, including
+ MESSAGE. REGEX and MESSAGE must not be NULL. */
+ gdb_regex (const char *regex, int cflags,
+ const char *message);
+ ~gdb_regex ();
+
+ /* Wrapper around ::regexec. */
+ int exec (const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+
+ /* Wrapper around ::re_search. */
+ int search (const char *string, int size,
+ int startpos, int range, struct re_registers *regs);
+
+private:
+ regex_t m_pattern;
+};
#endif /* not GDB_REGEX_H */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 016aadf..f424947 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -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,47 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
}
}
+struct mapping_regexes
+{
+ mapping_regexes ()
+ : dev_zero
+ ("^/dev/zero\\( (deleted)\\)\\?$", REG_NOSUB,
+ _("Could not compile regex to match /dev/zero filename")),
+ shmem_file
+ ("^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$", REG_NOSUB,
+ _("Could not compile regex to match shmem filenames")),
+ file_deleted
+ (" (deleted)$", REG_NOSUB,
+ _("Could not compile regex to match '<file> (deleted)'"))
+ {}
+
+ /* 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. */
+ gdb_regex dev_zero;
+
+ /* 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. */
+ gdb_regex shmem_file;
+
+ /* 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. */
+ gdb_regex 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 +548,13 @@ 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;
+ /* Like gdb::optional, but tristate. */
static int init_regex_p = 0;
+ static gdb::optional<mapping_regexes> regexes;
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;
diff --git a/gdb/probe.c b/gdb/probe.c
index e65e031..c8b92f3 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -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<gdb_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;
}
diff --git a/gdb/skip.c b/gdb/skip.c
index 4bd8a9e..65583d8 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -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<gdb_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);
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 22d81fa..1c1eb6c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -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<gdb_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. */
diff --git a/gdb/utils.c b/gdb/utils.c
index b4332f8..88a1789 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1038,58 +1038,6 @@ make_hex_string (const gdb_byte *data, size_t length)
\f
-/* 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
--
2.5.5
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 1/2] C++-ify break-catch-sig
2017-06-05 8:43 ` Simon Marchi
@ 2017-06-05 13:13 ` Tom Tromey
2017-06-05 13:53 ` Tom Tromey
1 sibling, 0 replies; 17+ messages in thread
From: Tom Tromey @ 2017-06-05 13:13 UTC (permalink / raw)
To: Simon Marchi; +Cc: Tom Tromey, gdb-patches
Simon> Although I'd prefer if you used "gdb_signal" instead of "auto"
Simon> here. It's not much longer, is more expressive. There are a few
Simon> instances of this throughout the patch.
I made this change. You might want to change the other uses of for/auto
already in gdb.
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 1/2] C++-ify break-catch-sig
2017-06-05 8:43 ` Simon Marchi
2017-06-05 13:13 ` Tom Tromey
@ 2017-06-05 13:53 ` Tom Tromey
1 sibling, 0 replies; 17+ messages in thread
From: Tom Tromey @ 2017-06-05 13:53 UTC (permalink / raw)
To: Simon Marchi; +Cc: Tom Tromey, gdb-patches
>> + gdb_signal iter;
Simon> You don't need this declaration...
There turned out to be many instances of this. I've fixed them all.
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-05 8:54 ` Simon Marchi
@ 2017-06-05 19:10 ` Tom Tromey
0 siblings, 0 replies; 17+ messages in thread
From: Tom Tromey @ 2017-06-05 19:10 UTC (permalink / raw)
To: Simon Marchi; +Cc: Tom Tromey, gdb-patches
>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:
Simon> From what I understand, we were freeing the regex with regfree, but we
Simon> weren't freeing the regex_t object, which is allocated separately, is
Simon> that right?
Yes, I think that's a leak in the current code.
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-05 12:29 ` Pedro Alves
2017-06-05 12:32 ` Pedro Alves
@ 2017-06-05 19:27 ` Tom Tromey
2017-06-06 16:22 ` Pedro Alves
1 sibling, 1 reply; 17+ messages in thread
From: Tom Tromey @ 2017-06-05 19:27 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
Pedro> So something like this. Builds and gdb starts, but I have
Pedro> not regtested it.
Thanks for doing this. I should have noticed the compile_rx_or_error
problem in my patch -- IIRC I wrote compile_rx_or_error and even
violated my own rule about cleanup naming (that cleanup-returning
functions should start "make_cleanup_") at the time. Double ouch.
Pedro> In a couple places, this either forces moving the regex object
Pedro> to the heap, or to wrap it in gdb::optional. In the cases
Pedro> where we already have to keep the regex string around,
Pedro> it ends up being not maximally efficient memory-wise, but I don't
Pedro> think it really matters. We're considering std::string for
Pedro> those same strings, which grows the structs more than that, anyway
Pedro> (for size/capacity).
I was thinking that perhaps the regexp object should just have its own
optionality. But, I think your way is also fine, maybe more principled
in a way.
I didn't look at all the cases, but at least for "catch throw" it
doesn't seem to matter much. For a few bytes in that structure to be a
problem, someone would have to use thousands or millions of catchpoints,
which seems absurd.
Pedro> WDYT?
Looks great, I will wait for this to land before round 2.
Pedro> +ada_add_standard_exceptions (gdb_regex *preg, VEC(ada_exc_info) **exceptions)
The various callees could use const if the exec method was const.
Pedro> + /* Compile a regexp and throw an exception on error, including
Pedro> + MESSAGE. REGEX and MESSAGE must not be NULL. */
Pedro> + gdb_regex (const char *regex, int cflags,
Pedro> + const char *message);
Use ATTRIBUTE_NONNULL?
Pedro> + /* Wrapper around ::regexec. */
Pedro> + int exec (const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
Pedro> +
Pedro> + /* Wrapper around ::re_search. */
Pedro> + int search (const char *string, int size,
Pedro> + int startpos, int range, struct re_registers *regs);
Could both be 'const', I think.
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-05 19:27 ` Tom Tromey
@ 2017-06-06 16:22 ` Pedro Alves
2017-06-07 12:38 ` Tom Tromey
0 siblings, 1 reply; 17+ messages in thread
From: Pedro Alves @ 2017-06-06 16:22 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 06/05/2017 08:27 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
>
> Pedro> So something like this. Builds and gdb starts, but I have
> Pedro> not regtested it.
>
> Thanks for doing this. I should have noticed the compile_rx_or_error
> problem in my patch -- IIRC I wrote compile_rx_or_error and even
> violated my own rule about cleanup naming (that cleanup-returning
> functions should start "make_cleanup_") at the time. Double ouch.
>
> Pedro> In a couple places, this either forces moving the regex object
> Pedro> to the heap, or to wrap it in gdb::optional. In the cases
> Pedro> where we already have to keep the regex string around,
> Pedro> it ends up being not maximally efficient memory-wise, but I don't
> Pedro> think it really matters. We're considering std::string for
> Pedro> those same strings, which grows the structs more than that, anyway
> Pedro> (for size/capacity).
>
> I was thinking that perhaps the regexp object should just have its own
> optionality. But, I think your way is also fine, maybe more principled
> in a way.
Yeah. Today I tried adding an optional_regex type that was a variant of
the gdb_regex from the previous patch, except that it also kept a pointer
to the source string, and then optionality was inferred from NULL-nesss of
that string pointer. It looked neat, until I stumbled on the fact that
some callers would like to pass an non-owning source string while
others want to pass in an owning string. I didn't feel like 3
regex types (compiled_regex, optional_regex and owning_optional_regex)
would really clarify things, so I kept it simple and rolled
back to what I had before. I renamed gdb_regex to compiled_regex
in the process though, and also realized that
linux-tdep.c:mapping_regexes would look a bit clearer with
in-class initialization.
>
> I didn't look at all the cases, but at least for "catch throw" it
> doesn't seem to matter much. For a few bytes in that structure to be a
> problem, someone would have to use thousands or millions of catchpoints,
> which seems absurd.
>
> Pedro> WDYT?
>
> Looks great, I will wait for this to land before round 2.
>
> Pedro> +ada_add_standard_exceptions (gdb_regex *preg, VEC(ada_exc_info) **exceptions)
>
> The various callees could use const if the exec method was const.
>
Done.
> Pedro> + /* Compile a regexp and throw an exception on error, including
> Pedro> + MESSAGE. REGEX and MESSAGE must not be NULL. */
> Pedro> + gdb_regex (const char *regex, int cflags,
> Pedro> + const char *message);
>
> Use ATTRIBUTE_NONNULL?
Done. Oddly, ATTRIBUTE_NONNULL takes only one argument, while
GCC's attribute nonnull takes a comma separated list of indexes.
That's why I'm specifying the attribute more than once (I checked
that it warned as expected).
>
> Pedro> + /* Wrapper around ::regexec. */
> Pedro> + int exec (const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
> Pedro> +
> Pedro> + /* Wrapper around ::re_search. */
> Pedro> + int search (const char *string, int size,
> Pedro> + int startpos, int range, struct re_registers *regs);
>
> Could both be 'const', I think.
That requires a const_cast in re_search, though. I've done that,
assuming that's just a const-correctness issue with the C API,
and that the buffer is not truly mutable at search time.
Thanks for the review. I've addressed all the above, I think, polished
it a bit, and ran regression tests.
WDYT?
From 625efedb75e4f1c25abc670109895b88de9edf9d Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 6 Jun 2017 17:16:26 +0100
Subject: [PATCH] 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-06 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 const
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 const 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 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.
---
gdb/Makefile.in | 2 ++
gdb/ada-lang.c | 33 ++++++++-----------
gdb/break-catch-throw.c | 21 +++++-------
gdb/breakpoint.c | 20 +++---------
gdb/cli/cli-cmds.c | 21 ++----------
gdb/cli/cli-decode.c | 11 ++++---
gdb/cli/cli-decode.h | 5 ++-
gdb/gdb_regex.c | 57 +++++++++++++++++++++++++++++++++
gdb/gdb_regex.h | 38 +++++++++++++++++++---
gdb/linux-tdep.c | 85 +++++++++++++++++++++++++------------------------
gdb/probe.c | 19 ++++++-----
gdb/skip.c | 24 +++-----------
gdb/symtab.c | 42 +++++++++---------------
gdb/utils.c | 52 ------------------------------
14 files changed, 204 insertions(+), 226 deletions(-)
create mode 100644 gdb/gdb_regex.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8be73ba..2156438 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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 \
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index f90907a..d7c3023 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -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 (const 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 (const 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, const 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 (const 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 (const 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)
- old_chain = compile_rx_or_error (®, regexp,
- _("invalid regular expression"));
+ if (regexp == NULL)
+ return ada_exceptions_list_1 (NULL);
- result = ada_exceptions_list_1 (regexp != NULL ? ® : 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 (®);
}
/* Implement the "info exceptions" command. */
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 7731c5e..0074d06 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -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;
};
\f
@@ -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 ());
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index e84d164..053ccef 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -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);
}
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 2a5b128..0930342 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -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.
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index d386d02..81d8165 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -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)
+ const compiled_regex ®ex, 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);
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index 66159fd..bf92344 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -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 *);
+ const 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
diff --git a/gdb/gdb_regex.c b/gdb/gdb_regex.c
new file mode 100644
index 0000000..2d00d92
--- /dev/null
+++ b/gdb/gdb_regex.c
@@ -0,0 +1,57 @@
+/* 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) const
+{
+ return re_search (const_cast<regex_t *> (&m_pattern),
+ string, length, start, range, regs);
+}
diff --git a/gdb/gdb_regex.h b/gdb/gdb_regex.h
index 0be26ef..7873231 100644
--- a/gdb/gdb_regex.h
+++ b/gdb/gdb_regex.h
@@ -27,10 +27,38 @@
# 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. */
+ int search (const char *string, int size, int startpos,
+ int range, struct re_registers *regs) const;
+
+private:
+ /* The compiled pattern. */
+ regex_t m_pattern;
+};
#endif /* not GDB_REGEX_H */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 016aadf..1afa8d7 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -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;
diff --git a/gdb/probe.c b/gdb/probe.c
index e65e031..cb2dcdb 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -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;
}
diff --git a/gdb/skip.c b/gdb/skip.c
index 4bd8a9e..e767f83 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -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);
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 22d81fa..f1daf8c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -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. */
diff --git a/gdb/utils.c b/gdb/utils.c
index b4332f8..88a1789 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1038,58 +1038,6 @@ make_hex_string (const gdb_byte *data, size_t length)
\f
-/* 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
--
2.5.5
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFA 2/2] C++-ify break-catch-throw
2017-06-06 16:22 ` Pedro Alves
@ 2017-06-07 12:38 ` Tom Tromey
2017-06-07 13:40 ` [pushed] Introduce compiled_regex, eliminate make_regfree_cleanup (Re: [RFA 2/2] C++-ify break-catch-throw) Pedro Alves
0 siblings, 1 reply; 17+ messages in thread
From: Tom Tromey @ 2017-06-07 12:38 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
Pedro> That requires a const_cast in re_search, though. I've done that,
Pedro> assuming that's just a const-correctness issue with the C API,
Pedro> and that the buffer is not truly mutable at search time.
Now I am not sure, given libiberty/regex.c:re_compile_fastmap.
Pedro> WDYT?
Looks great.
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* [pushed] Introduce compiled_regex, eliminate make_regfree_cleanup (Re: [RFA 2/2] C++-ify break-catch-throw)
2017-06-07 12:38 ` Tom Tromey
@ 2017-06-07 13:40 ` Pedro Alves
0 siblings, 0 replies; 17+ messages in thread
From: Pedro Alves @ 2017-06-07 13:40 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 06/07/2017 01:38 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
>
> Pedro> That requires a const_cast in re_search, though. I've done that,
> Pedro> assuming that's just a const-correctness issue with the C API,
> Pedro> and that the buffer is not truly mutable at search time.
>
> Now I am not sure, given libiberty/regex.c:re_compile_fastmap.
Indeed, thanks for checking! I've left the const in compiled_regex::exec,
but removed it from compiled_regex::search and elsewhere, even when
not strictly necessary, assuming a callee might reasonably want to call
search at some point.
>
> Pedro> WDYT?
>
> Looks great.
>
Here's what I pushed, then.
From 2d7cc5c7973b6d1bdd9205288863bedadeaf8b41 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Wed, 7 Jun 2017 14:21:40 +0100
Subject: [PATCH] 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.
---
gdb/ChangeLog | 51 +++++++++++++++++++++++++++++
gdb/Makefile.in | 2 ++
gdb/ada-lang.c | 33 ++++++++-----------
gdb/break-catch-throw.c | 21 +++++-------
gdb/breakpoint.c | 20 +++---------
gdb/cli/cli-cmds.c | 21 ++----------
gdb/cli/cli-decode.c | 11 ++++---
gdb/cli/cli-decode.h | 5 ++-
gdb/gdb_regex.c | 56 ++++++++++++++++++++++++++++++++
gdb/gdb_regex.h | 39 ++++++++++++++++++++---
gdb/linux-tdep.c | 85 +++++++++++++++++++++++++------------------------
gdb/probe.c | 19 ++++++-----
gdb/skip.c | 24 +++-----------
gdb/symtab.c | 42 +++++++++---------------
gdb/utils.c | 52 ------------------------------
15 files changed, 255 insertions(+), 226 deletions(-)
create mode 100644 gdb/gdb_regex.c
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3190410..6424388 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8be73ba..2156438 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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 \
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index f90907a..57c670e 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -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)
- old_chain = compile_rx_or_error (®, regexp,
- _("invalid regular expression"));
+ if (regexp == NULL)
+ return ada_exceptions_list_1 (NULL);
- result = ada_exceptions_list_1 (regexp != NULL ? ® : 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 (®);
}
/* Implement the "info exceptions" command. */
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 7731c5e..0074d06 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -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;
};
\f
@@ -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 ());
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index e84d164..053ccef 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -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);
}
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 2a5b128..0930342 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -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.
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index d386d02..383adf8 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -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 ®ex, 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);
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index 66159fd..11248ba 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -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
diff --git a/gdb/gdb_regex.c b/gdb/gdb_regex.c
new file mode 100644
index 0000000..2e376e3
--- /dev/null
+++ b/gdb/gdb_regex.c
@@ -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);
+}
diff --git a/gdb/gdb_regex.h b/gdb/gdb_regex.h
index 0be26ef..f62f81d 100644
--- a/gdb/gdb_regex.h
+++ b/gdb/gdb_regex.h
@@ -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 */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 016aadf..1afa8d7 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -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;
diff --git a/gdb/probe.c b/gdb/probe.c
index e65e031..cb2dcdb 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -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;
}
diff --git a/gdb/skip.c b/gdb/skip.c
index 4bd8a9e..e767f83 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -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);
}
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 22d81fa..f1daf8c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -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. */
diff --git a/gdb/utils.c b/gdb/utils.c
index b4332f8..88a1789 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1038,58 +1038,6 @@ make_hex_string (const gdb_byte *data, size_t length)
\f
-/* 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
--
2.5.5
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2017-06-07 13:40 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-04 22:54 [RFA 0/2] C++-ify some breakpoint subclasses a bit more Tom Tromey
2017-06-04 22:54 ` [RFA 1/2] C++-ify break-catch-sig Tom Tromey
2017-06-05 8:43 ` Simon Marchi
2017-06-05 13:13 ` Tom Tromey
2017-06-05 13:53 ` Tom Tromey
2017-06-04 22:54 ` [RFA 2/2] C++-ify break-catch-throw Tom Tromey
2017-06-05 8:54 ` Simon Marchi
2017-06-05 19:10 ` Tom Tromey
2017-06-05 10:21 ` Pedro Alves
2017-06-05 10:33 ` Pedro Alves
2017-06-05 10:36 ` Pedro Alves
2017-06-05 12:29 ` Pedro Alves
2017-06-05 12:32 ` Pedro Alves
2017-06-05 19:27 ` Tom Tromey
2017-06-06 16:22 ` Pedro Alves
2017-06-07 12:38 ` Tom Tromey
2017-06-07 13:40 ` [pushed] Introduce compiled_regex, eliminate make_regfree_cleanup (Re: [RFA 2/2] C++-ify break-catch-throw) Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).