diff --git a/gdb/python/python.c b/gdb/python/python.c
index ddf0e72d26f..05ad038865a 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -645,19 +645,6 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
 static PyObject *
 gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
 {
-  /* A simple type to ensure clean up of a vector of allocated strings
-     when a C interface demands a const char *array[] type
-     interface.  */
-  struct symtab_list_type
-  {
-    ~symtab_list_type ()
-    {
-      for (const char *elem: vec)
-	xfree ((void *) elem);
-    }
-    std::vector<const char *> vec;
-  };
-
   char *regex = NULL;
   std::vector<symbol_search> symbols;
   unsigned long count = 0;
@@ -667,7 +654,6 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
   unsigned int throttle = 0;
   static const char *keywords[] = {"regex","minsyms", "throttle",
 				   "symtabs", NULL};
-  symtab_list_type symtab_paths;
 
   if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!IO", keywords,
 					&regex, &PyBool_Type,
@@ -684,6 +670,26 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
       minsyms_p = cmp;
     }
 
+  /* A wrapper around search_symbols_spec in order to call free the
+     strings held in the filenames vector.  */
+  struct python_rbreak_search_symbols_spec
+  {
+    search_symbols_spec spec;
+
+    python_rbreak_search_symbols_spec (const char *regex)
+      : spec (FUNCTIONS_DOMAIN, regex)
+    { /* Nothing.  */ }
+
+    ~python_rbreak_search_symbols_spec ()
+    {
+      for (const char *elem: spec.filenames)
+	xfree ((void *) elem);
+    }
+  };
+
+  /* The search spec.  */
+  python_rbreak_search_symbols_spec spec (regex);
+
   /* The "symtabs" keyword is any Python iterable object that returns
      a gdb.Symtab on each iteration.  If specified, iterate through
      the provided gdb.Symtabs and extract their full path.  As
@@ -729,20 +735,12 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
 
 	  /* Make sure there is a definite place to store the value of
 	     filename before it is released.  */
-	  symtab_paths.vec.push_back (nullptr);
-	  symtab_paths.vec.back () = filename.release ();
+	  spec.spec.filenames.push_back (nullptr);
+	  spec.spec.filenames.back () = filename.release ();
 	}
     }
 
-  if (symtab_list)
-    {
-      const char **files = symtab_paths.vec.data ();
-
-      symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL,
-				symtab_paths.vec.size (), files, false);
-    }
-  else
-    symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL, 0, NULL, false);
+  symbols = search_symbols (spec.spec);
 
   /* Count the number of symbols (both symbols and optionally minimal
      symbols) so we can correctly check the throttle limit.  */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 21ac57c39a9..b7b65b98ac8 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4331,26 +4331,23 @@ info_sources_command (const char *args, int from_tty)
   printf_filtered ("\n");
 }
 
-/* Compare FILE against all the NFILES entries of FILES.  If BASENAMES is
-   non-zero compare only lbasename of FILES.  */
+/* Compare FILE against all the entries of FILENAMES.  If BASENAMES is
+   non-zero compare only lbasename of FILENAMES.  */
 
-static int
-file_matches (const char *file, const char *files[], int nfiles, int basenames)
+static bool
+file_matches (const char *file, const std::vector<const char *> &filenames,
+	      bool basenames)
 {
-  int i;
+  if (filenames.size () == 0)
+    return 1;
 
-  if (file != NULL && nfiles != 0)
+  for (const char *name : filenames)
     {
-      for (i = 0; i < nfiles; i++)
-	{
-	  if (compare_filenames_for_search (file, (basenames
-						   ? lbasename (files[i])
-						   : files[i])))
-	    return 1;
-	}
+      name = (basenames ? lbasename (name) : name);
+      if (compare_filenames_for_search (file, name))
+	return 1;
     }
-  else if (nfiles == 0)
-    return 1;
+
   return 0;
 }
 
@@ -4428,31 +4425,19 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
 		 result->end ());
 }
 
-/* Search the symbol table for matches to the regular expression REGEXP,
-   returning the results.
-
-   Only symbols of KIND are searched:
-   VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
-                      and constants (enums).
-		      if T_REGEXP is not NULL, only returns var that have
-		      a type matching regular expression T_REGEXP.
-   FUNCTIONS_DOMAIN - search all functions
-   TYPES_DOMAIN     - search all type names
-   ALL_DOMAIN       - an internal error for this function
-
-   Within each file the results are sorted locally; each symtab's global and
-   static blocks are separately alphabetized.
-   Duplicate entries are removed.
-
-   When EXCLUDE_MINSYMS is false then matching minsyms are also returned,
-   otherwise they are excluded.  */
+/* See symtab.h.  */
 
 std::vector<symbol_search>
-search_symbols (const char *regexp, enum search_domain kind,
-		const char *t_regexp,
-		int nfiles, const char *files[],
-		bool exclude_minsyms)
+search_symbols (const search_symbols_spec &search_spec)
 {
+  /* Unpack the search spec.  */
+  const char *regexp = search_spec.symbol_regexp;
+  enum search_domain kind = search_spec.kind;
+  const char *t_regexp = search_spec.type_regexp;
+  int nfiles = search_spec.filenames.size ();
+  bool exclude_minsyms = search_spec.exclude_minsyms;
+
+  /* The search.  */
   const struct blockvector *bv;
   const struct block *b;
   int i = 0;
@@ -4535,8 +4520,12 @@ search_symbols (const char *regexp, enum search_domain kind,
      the machinery below.  */
   expand_symtabs_matching ([&] (const char *filename, bool basenames)
 			   {
-			     return file_matches (filename, files, nfiles,
-						  basenames);
+			     /* EXPAND_SYMTABS_MATCHING expects a callback
+				that returns an integer, not a boolean as
+				FILE_MATCHES does.  */
+			     return file_matches (filename,
+						  search_spec.filenames,
+						  basenames) ? 1 : 0;
 			   },
 			   lookup_name_info::match_any (),
 			   [&] (const char *symname)
@@ -4620,12 +4609,13 @@ search_symbols (const char *regexp, enum search_domain kind,
 		  /* Check first sole REAL_SYMTAB->FILENAME.  It does
 		     not need to be a substring of symtab_to_fullname as
 		     it may contain "./" etc.  */
-		  if ((file_matches (real_symtab->filename, files, nfiles, 0)
+		  if ((file_matches (real_symtab->filename,
+				     search_spec.filenames, false)
 		       || ((basenames_may_differ
 			    || file_matches (lbasename (real_symtab->filename),
-					     files, nfiles, 1))
+					     search_spec.filenames, true))
 			   && file_matches (symtab_to_fullname (real_symtab),
-					    files, nfiles, 0)))
+					    search_spec.filenames, false)))
 		      && ((!preg.has_value ()
 			   || preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
 					  NULL, 0) == 0)
@@ -4836,9 +4826,8 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
     regexp = nullptr;
 
   /* Must make sure that if we're interrupted, symbols gets freed.  */
-  std::vector<symbol_search> symbols = search_symbols (regexp, kind,
-						       t_regexp, 0, NULL,
-						       exclude_minsyms);
+  search_symbols_spec spec (kind, regexp, t_regexp, exclude_minsyms);
+  std::vector<symbol_search> symbols = search_symbols (spec);
 
   if (!quiet)
     {
@@ -5077,11 +5066,9 @@ static void
 rbreak_command (const char *regexp, int from_tty)
 {
   std::string string;
-  const char **files = NULL;
-  const char *file_name;
-  int nfiles = 0;
+  const char *file_name = nullptr;
 
-  if (regexp)
+  if (regexp != nullptr)
     {
       const char *colon = strchr (regexp, ':');
 
@@ -5097,17 +5084,14 @@ rbreak_command (const char *regexp, int from_tty)
 	  while (isspace (local_name[colon_index]))
 	    local_name[colon_index--] = 0;
 	  file_name = local_name;
-	  files = &file_name;
-	  nfiles = 1;
 	  regexp = skip_spaces (colon + 1);
 	}
     }
 
-  std::vector<symbol_search> symbols = search_symbols (regexp,
-						       FUNCTIONS_DOMAIN,
-						       NULL,
-						       nfiles, files,
-						       false);
+  search_symbols_spec spec (FUNCTIONS_DOMAIN, regexp);
+  if (file_name != nullptr)
+    spec.filenames.push_back (file_name);
+  std::vector<symbol_search> symbols = search_symbols (spec);
 
   scoped_rbreak_breakpoints finalize;
   for (const symbol_search &p : symbols)
@@ -6352,17 +6336,14 @@ search_module_symbols (const char *module_regexp, const char *regexp,
   std::vector<module_symbol_search> results;
 
   /* Search for all modules matching MODULE_REGEXP.  */
-  std::vector<symbol_search> modules = search_symbols (module_regexp,
-						       MODULES_DOMAIN,
-						       NULL, 0, NULL,
-						       true);
+  search_symbols_spec spec1 (MODULES_DOMAIN, module_regexp, nullptr, true);
+  std::vector<symbol_search> modules = search_symbols (spec1);
 
   /* Now search for all symbols of the required KIND matching the required
      regular expressions.  We figure out which ones are in which modules
      below.  */
-  std::vector<symbol_search> symbols = search_symbols (regexp, kind,
-						       type_regexp, 0,
-						       NULL, true);
+  search_symbols_spec spec2 (kind, regexp, type_regexp, true);
+  std::vector<symbol_search> symbols = search_symbols (spec2);
 
   /* Now iterate over all MODULES, checking to see which items from
      SYMBOLS are in each module.  */
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 6bd8873042f..f1c7db22505 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2064,12 +2064,52 @@ private:
 				  const symbol_search &sym_b);
 };
 
-extern std::vector<symbol_search> search_symbols (const char *,
-						  enum search_domain,
-						  const char *,
-						  int,
-						  const char **,
-						  bool);
+/* When searching for symbols using the SEARCH_SYMBOLS function, one of
+   these structures is used as the search specification.  */
+struct search_symbols_spec
+{
+  /* The kind of symbols are we searching for.
+     VARIABLES_DOMAIN - Search all symbols, excluding functions, type
+                        names, and constants (enums).
+     FUNCTIONS_DOMAIN - Search all functions..
+     TYPES_DOMAIN     - Search all type names.
+     MODULES_DOMAIN   - Search all Fortran modules.
+     ALL_DOMAIN       - Not valid for this function.  */
+  enum search_domain kind;
+
+  /* Regular expression to match against the symbol name.  */
+  const char *symbol_regexp = nullptr;
+
+  /* Regular expression to match against the type of the symbol.  */
+  const char *type_regexp = nullptr;
+
+  /* When this flag is false then minsyms that match SYMBOL_REGEXP will be
+     included in the results, otherwise they are excluded.  */
+  bool exclude_minsyms = false;
+
+  /* The set of source files to search in for matching symbols.  */
+  std::vector<const char *> filenames;
+
+  /* Constructor.  */
+  search_symbols_spec (enum search_domain kind,
+		       const char *symbol_regexp = nullptr,
+		       const char *type_regexp = nullptr,
+		       bool exclude_minsyms = false)
+    : kind (kind),
+      symbol_regexp (symbol_regexp),
+      type_regexp (type_regexp),
+      exclude_minsyms (exclude_minsyms)
+  { /* Nothing.  */ }
+};
+
+/* Search the symbol table for matches as defined by SEARCH_SPEC.
+
+   Within each file the results are sorted locally; each symtab's global
+   and static blocks are separately alphabetized.  Duplicate entries are
+   removed.  */
+
+extern std::vector<symbol_search> search_symbols
+	(const struct search_symbols_spec &search_spec);
 
 /* When searching for Fortran symbols within modules (functions/variables)
    we return a vector of this type.  The first item in the pair is the
