diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a21e06c..c3199e3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,28 @@
 2019-12-02  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+	* mi/mi-symbol-cmds.c (mi_symbol_info): Take extra parameter, and
+	add it into the search spec.
+	(mi_info_functions_or_variables): Parse -max-results flag and pass
+	it to mi_symbol_info.
+	(mi_cmd_symbol_info_modules): Likewise.
+	(mi_cmd_symbol_info_types): Likewise.
+	* symtab.c (global_symbol_searcher::add_matching_symbols): Change
+	return type to bool, don't add new results if we have enough
+	already.
+	(global_symbol_searcher::add_matching_msymbols): Likewise.
+	(global_symbol_searcher::search): Early exit from search loop when
+	we have enough results.
+	* symtab.h (global_symbol_searcher) <set_max_seach_results>: New
+	member function.
+	(global_symbol_searcher) <m_max_search_results>: New member
+	variable.
+	(global_symbol_searcher) <add_matching_symbols>: Update header
+	comment and change return type to bool.
+	(global_symbol_searcher) <add_matching_msymbols>: Update header
+	comment and change return type to bool.
+
+2019-12-02  Andrew Burgess  <andrew.burgess@embecosm.com>
+
 	* symtab.c (symbol_search::compare_search_syms): Update header
 	comment.
 	(global_symbol_searcher::is_suitable_msymbol): New function.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 10e2207..df6026f 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,5 +1,10 @@
 2019-12-02  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+	* doc/gdb.texinfo (GDB/MI Symbol Query): Add documentation of
+	-max-results to some -symbol-info-* commands.
+
+2019-12-02  Andrew Burgess  <andrew.burgess@embecosm.com>
+
 	* doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command
 	-symbol-info-module-functions and -symbol-info-module-variables.
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6fb7e8a..544e632 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -33962,6 +33962,7 @@
  -symbol-info-functions [--include-nondebug]
                         [--type @var{type_regexp}]
                         [--name @var{name_regexp}]
+                        [--max-results @var{limit}]
 @end smallexample
 
 @noindent
@@ -33977,6 +33978,11 @@
 to be filtered based on either the name of the function, or the type
 signature of the function.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info functions}.
@@ -34208,6 +34214,8 @@
 
 @smallexample
  -symbol-info-modules [--name @var{name_regexp}]
+                      [--max-results @var{limit}]
+
 @end smallexample
 
 @noindent
@@ -34218,6 +34226,11 @@
 The option @code{--name} allows the modules returned to be filtered
 based the name of the module.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info modules}.
@@ -34262,6 +34275,8 @@
 
 @smallexample
  -symbol-info-types [--name @var{name_regexp}]
+                    [--max-results @var{limit}]
+
 @end smallexample
 
 @noindent
@@ -34275,6 +34290,11 @@
 The option @code{--name} allows the list of types returned to be
 filtered by name.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info types}.
@@ -34322,6 +34342,8 @@
  -symbol-info-variables [--include-nondebug]
                         [--type @var{type_regexp}]
                         [--name @var{name_regexp}]
+                        [--max-results @var{limit}]
+
 @end smallexample
 
 @noindent
@@ -34337,6 +34359,11 @@
 to be filtered based on either the name of the variable, or the type
 of the variable.
 
+The option @code{--max-results} restricts the command to return no
+more than @var{limit} results.  If exactly @var{limit} results are
+returned then there might be additional results available if a higher
+limit is used.
+
 @subsubheading @value{GDBN} Command
 
 The corresponding @value{GDBN} command is @samp{info variables}.
diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c
index 6334e39..8bc6c26 100644
--- a/gdb/mi/mi-symbol-cmds.c
+++ b/gdb/mi/mi-symbol-cmds.c
@@ -111,11 +111,13 @@
 
 static void
 mi_symbol_info (enum search_domain kind, const char *name_regexp,
-		const char *type_regexp, bool exclude_minsyms)
+		const char *type_regexp, bool exclude_minsyms,
+		unsigned int max_results)
 {
   global_symbol_searcher sym_search (kind, name_regexp);
   sym_search.set_symbol_type_regexp (type_regexp);
   sym_search.set_exclude_minsyms (exclude_minsyms);
+  sym_search.set_max_search_results (max_results);
   std::vector<symbol_search> symbols = sym_search.search ();
   ui_out *uiout = current_uiout;
   int i = 0;
@@ -172,19 +174,21 @@
 static void
 mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc)
 {
+  unsigned int max_results = UINT_MAX;
   const char *regexp = nullptr;
   const char *t_regexp = nullptr;
   bool exclude_minsyms = true;
 
   enum opt
     {
-     INCLUDE_NONDEBUG_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT
+     INCLUDE_NONDEBUG_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT, MAX_RESULTS_OPT
     };
   static const struct mi_opt opts[] =
   {
     {"-include-nondebug" , INCLUDE_NONDEBUG_OPT, 0},
     {"-type", TYPE_REGEXP_OPT, 1},
     {"-name", NAME_REGEXP_OPT, 1},
+    {"-max-results", MAX_RESULTS_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -210,10 +214,19 @@
 	case NAME_REGEXP_OPT:
 	  regexp = oarg;
 	  break;
+	case MAX_RESULTS_OPT:
+	  {
+	    char *eptr = oarg;
+	    long val = strtol (oarg, &eptr, 10);
+	    if (oarg == eptr || val > UINT_MAX || val < 0)
+	      error (_("invalid value for --max-results argument"));
+	    max_results = (unsigned int) val;
+	  }
+	  break;
 	}
     }
 
-  mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms);
+  mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms, max_results);
 }
 
 /* Helper for mi_info_module_functions_or_variables.  Display the results
@@ -382,15 +395,17 @@
 void
 mi_cmd_symbol_info_modules (const char *command, char **argv, int argc)
 {
+  unsigned int max_results = UINT_MAX;
   const char *regexp = nullptr;
 
   enum opt
     {
-     NAME_REGEXP_OPT
+     NAME_REGEXP_OPT, MAX_RESULTS_OPT
     };
   static const struct mi_opt opts[] =
   {
     {"-name", NAME_REGEXP_OPT, 1},
+    {"-max-results", MAX_RESULTS_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -408,10 +423,19 @@
 	case NAME_REGEXP_OPT:
 	  regexp = oarg;
 	  break;
+	case MAX_RESULTS_OPT:
+	  {
+	    char *eptr = oarg;
+	    long val = strtol (oarg, &eptr, 10);
+	    if (oarg == eptr || val > UINT_MAX || val < 0)
+	      error (_("invalid value for --max-results argument"));
+	    max_results = (unsigned int) val;
+	  }
+	  break;
 	}
     }
 
-  mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true);
+  mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true, max_results);
 }
 
 /* Implement -symbol-info-types command.  */
@@ -419,15 +443,17 @@
 void
 mi_cmd_symbol_info_types (const char *command, char **argv, int argc)
 {
+  unsigned int max_results = UINT_MAX;
   const char *regexp = nullptr;
 
   enum opt
     {
-     NAME_REGEXP_OPT
+     NAME_REGEXP_OPT, MAX_RESULTS_OPT
     };
   static const struct mi_opt opts[] =
   {
     {"-name", NAME_REGEXP_OPT, 1},
+    {"-max-results", MAX_RESULTS_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -445,10 +471,19 @@
 	case NAME_REGEXP_OPT:
 	  regexp = oarg;
 	  break;
+	case MAX_RESULTS_OPT:
+	  {
+	    char *eptr = oarg;
+	    long val = strtol (oarg, &eptr, 10);
+	    if (oarg == eptr || val > UINT_MAX || val < 0)
+	      error (_("invalid value for --max-results argument"));
+	    max_results = (unsigned int) val;
+	  }
+	  break;
 	}
     }
 
-  mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true);
+  mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true, max_results);
 }
 
 /* Implement -symbol-info-variables command.  */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 0e92d4a..16dca72 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4534,7 +4534,7 @@
 
 /* See symtab.h.  */
 
-void
+bool
 global_symbol_searcher::add_matching_symbols
 	(objfile *objfile,
 	 const gdb::optional<compiled_regex> &preg,
@@ -4597,19 +4597,26 @@
 			      && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
 			      && SYMBOL_LINE (sym) != 0))))
 		{
-		  /* Match, insert if not already in the results.  */
-		  symbol_search ss (block, sym);
-		  if (result_set->find (ss) == result_set->end ())
-		    result_set->insert (ss);
+		  if (result_set->size () < m_max_search_results)
+		    {
+		      /* Match, insert if not already in the results.  */
+		      symbol_search ss (block, sym);
+		      if (result_set->find (ss) == result_set->end ())
+			result_set->insert (ss);
+		    }
+		  else
+		    return false;
 		}
 	    }
 	}
     }
+
+  return true;
 }
 
 /* See symtab.h.  */
 
-void
+bool
 global_symbol_searcher::add_matching_msymbols
 	(objfile *objfile, const gdb::optional<compiled_regex> &preg,
 	 std::vector<symbol_search> *results) const
@@ -4641,12 +4648,17 @@
 		       VAR_DOMAIN).symbol == NULL)
 		    {
 		      /* Matching msymbol, add it to the results list.  */
-		      results->emplace_back (GLOBAL_BLOCK, msymbol, objfile);
+		      if (results->size () < m_max_search_results)
+			results->emplace_back (GLOBAL_BLOCK, msymbol, objfile);
+		      else
+			return false;
 		    }
 		}
 	    }
 	}
     }
+
+  return true;
 }
 
 /* See symtab.h.  */
@@ -4721,7 +4733,8 @@
 
       /* Find matching symbols within OBJFILE and add them in to
 	 RESULT_SET.  */
-      add_matching_symbols (objfile, preg, treg, &result_set);
+      if (!add_matching_symbols (objfile, preg, treg, &result_set))
+	break;
     }
 
   /* Convert the result set into a sorted result list.  */
@@ -4738,7 +4751,8 @@
     {
       gdb_assert (m_kind == VARIABLES_DOMAIN || m_kind == FUNCTIONS_DOMAIN);
       for (objfile *objfile : current_program_space->objfiles ())
-	add_matching_msymbols (objfile, preg, &result);
+	if (!add_matching_msymbols (objfile, preg, &result))
+	  break;
     }
 
   return result;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index f183083..d0fc20d 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2093,6 +2093,12 @@
     m_exclude_minsyms = exclude_minsyms;
   }
 
+  /* Set the maximum number of search results to be returned.  */
+  void set_max_search_results (unsigned int max_search_results)
+  {
+    m_max_search_results = max_search_results;
+  }
+
   /* Search the symbols from all objfiles in the current program space
      looking for matches as defined by the current state of this object.
 
@@ -2126,6 +2132,10 @@
      be included in the results, otherwise they are excluded.  */
   bool m_exclude_minsyms = false;
 
+  /* Maximum number of search results.  We currently impose a hard limit
+     of UINT_MAX, there is no "unlimited".  */
+  unsigned int m_max_search_results = UINT_MAX;
+
   /* Expand symtabs in OBJFILE that match PREG, are of type M_KIND.  Return
      true if any msymbols were seen that we should later consider adding to
      the results list.  */
@@ -2133,15 +2143,23 @@
 		       const gdb::optional<compiled_regex> &preg) const;
 
   /* Add symbols from symtabs in OBJFILE that match PREG, and TREG, and are
-     of type M_KIND, to the results set RESULTS_SET.  */
-  void add_matching_symbols (objfile *objfile,
+     of type M_KIND, to the results set RESULTS_SET.  Return false if we
+     stop adding results early due to having already found too many results
+     (based on M_MAX_SEARCH_RESULTS limit), otherwise return true.
+     Returning true does not indicate that any results were added, just
+     that we didn't _not_ add a result due to reaching MAX_SEARCH_RESULTS.  */
+  bool add_matching_symbols (objfile *objfile,
 			     const gdb::optional<compiled_regex> &preg,
 			     const gdb::optional<compiled_regex> &treg,
 			     std::set<symbol_search> *result_set) const;
 
-  /* Add msymbols from OBJFILE that match PREG and M_KIND, to the
-     results vector RESULTS.  */
-  void add_matching_msymbols (objfile *objfile,
+  /* Add msymbols from OBJFILE that match PREG and M_KIND, to the results
+     vector RESULTS.  Return false if we stop adding results early due to
+     having already found too many results (based on max search results
+     limit M_MAX_SEARCH_RESULTS), otherwise return true.  Returning true
+     does not indicate that any results were added, just that we didn't
+     _not_ add a result due to reaching MAX_SEARCH_RESULTS.  */
+  bool add_matching_msymbols (objfile *objfile,
 			      const gdb::optional<compiled_regex> &preg,
 			      std::vector<symbol_search> *results) const;
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 7fa48e3..765fb84 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
 2019-12-02  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+	* gdb.mi/mi-sym-info.exp: Add tests for -max-results parameter.
+
+2019-12-02  Andrew Burgess  <andrew.burgess@embecosm.com>
+
 	* gdb.mi/mi-fortran-modules.exp: Add additional tests for
 	-symbol-info-module-functions and -symbol-info-module-variables.
 
diff --git a/gdb/testsuite/gdb.mi/mi-sym-info.exp b/gdb/testsuite/gdb.mi/mi-sym-info.exp
index 33fe865..4a65bd6 100644
--- a/gdb/testsuite/gdb.mi/mi-sym-info.exp
+++ b/gdb/testsuite/gdb.mi/mi-sym-info.exp
@@ -127,3 +127,24 @@
 mi_gdb_test "120-symbol-info-types --name _int_" \
     "120\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"27\",name=\"my_int_t\"\}\\\]\},\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"23\",name=\"another_int_t\"\}\\\]\}\\\]\}" \
     "List all types matching _int_"
+
+# Test the --max-results parameter.
+mi_gdb_test "121-symbol-info-functions --max-results 0" \
+    "121\\^done,symbols=\{\}" \
+    "-symbol-info-functions --max-results 0"
+
+mi_gdb_test "122-symbol-info-functions --max-results 1" \
+    "122\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"39\",name=\"f3\",type=\"int \\(another_int_t\\)\",description=\"int f3\\(another_int_t\\);\"\}\\\]\}\\\]\}" \
+    "-symbol-info-functions --max-results 1"
+
+mi_gdb_test "123-symbol-info-functions --max-results 2" \
+    "123\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"33\",name=\"f2\",type=\"float \\(another_float_t\\)\",description=\"float f2\\(another_float_t\\);\"\},\{line=\"39\",name=\"f3\",type=\"int \\(another_int_t\\)\",description=\"int f3\\(another_int_t\\);\"\}\\\]\}\\\]\}" \
+    "-symbol-info-functions --max-results 2"
+
+mi_gdb_test "124-symbol-info-variables --max-results 3" \
+    "124\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"global_f2\",type=\"int\",description=\"int global_f2;\"\},\{line=\"20\",name=\"global_i2\",type=\"int\",description=\"int global_i2;\"\},\{line=\"19\",name=\"global_f1\",type=\"float\",description=\"static float global_f1;\"\}\\\]\}\\\]\}" \
+    "-symbol-info-variables --max-results 3"
+
+mi_gdb_test "125-symbol-info-types --max-results 4" \
+    "125\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"24\",name=\"another_float_t\"\},\{line=\"23\",name=\"another_int_t\"\},\{name=\"float\"\},\{name=\"int\"\}\\\]\}\\\]\}" \
+    "-symbol-info-types --max-results 4"
