From patchwork Mon Jun 5 12:32:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 20794 Received: (qmail 60454 invoked by alias); 5 Jun 2017 12:32:11 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 59829 invoked by uid 89); 5 Jun 2017 12:32:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_STOCKGEN, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 05 Jun 2017 12:32:06 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 40CBF80C10; Mon, 5 Jun 2017 12:32:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 40CBF80C10 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=palves@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 40CBF80C10 Received: from [127.0.0.1] (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2CF8380A2F; Mon, 5 Jun 2017 12:32:07 +0000 (UTC) Subject: Re: [RFA 2/2] C++-ify break-catch-throw To: Tom Tromey , gdb-patches@sourceware.org References: <20170604225353.18008-1-tom@tromey.com> <20170604225353.18008-3-tom@tromey.com> <01e777c7-a287-8dfe-dd21-370690ed6629@redhat.com> <19aada83-3165-d488-c5ca-5de7f4b4f1ca@redhat.com> From: Pedro Alves Message-ID: <42eac5c9-4983-15bd-d728-b3973e562f5f@redhat.com> Date: Mon, 5 Jun 2017 13:32:07 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: 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 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 pattern; }; @@ -145,8 +145,6 @@ classify_exception_breakpoint (struct breakpoint *b) exception_catchpoint::~exception_catchpoint () { xfree (this->exception_rx); - if (this->pattern != NULL) - regfree (this->pattern); } /* Implement the 'check_status' method. */ @@ -185,7 +183,7 @@ check_status_exception_catchpoint (struct bpstats *bs) if (!type_name.empty ()) { - if (regexec (self->pattern, type_name.c_str (), 0, NULL, 0) != 0) + if (self->pattern->exec (type_name.c_str (), 0, NULL, 0) != 0) bs->stop = 0; } } @@ -377,15 +375,12 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx, const char *cond_string, enum exception_event_kind ex_event, int from_tty) { - regex_t *pattern = NULL; + std::unique_ptr 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 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 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 . + + 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 . */ + +#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 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 #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 @@ -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 ' (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 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 " - "' (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 #include +#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 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 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 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) -/* 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