public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Maciej W. Rozycki" <macro@embecosm.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>, Tom Tromey <tom@tromey.com>,
	 Richard Bunt <Richard.Bunt@arm.com>
Subject: [PATCH v3 5/5] GDB: Introduce limited array lengths while printing values
Date: Mon, 23 Jan 2023 23:14:35 +0000 (GMT)	[thread overview]
Message-ID: <alpine.DEB.2.20.2301211719580.7841@tpp.orcam.me.uk> (raw)
In-Reply-To: <alpine.DEB.2.20.2301210444350.7841@tpp.orcam.me.uk>

From: Andrew Burgess <andrew.burgess@embecosm.com>

This commit introduces the idea of loading only part of an array in 
order to print it, what I call "limited length" arrays.

The motivation behind this work is to make it possible to print slices 
of very large arrays, where very large means bigger than 
`max-value-size'.

Consider this GDB session with the current GDB:

  (gdb) set max-value-size 100
  (gdb) p large_1d_array
  value requires 400 bytes, which is more than max-value-size
  (gdb) p -elements 10 -- large_1d_array
  value requires 400 bytes, which is more than max-value-size

notice that the request to print 10 elements still fails, even though 10 
elements should be less than the max-value-size.  With a patched version 
of GDB:

  (gdb) p -elements 10 -- large_1d_array
  $1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9...}

So now the print has succeeded.  It also has loaded `max-value-size' 
worth of data into value history, so the recorded value can be accessed 
consistently:

  (gdb) p -elements 10 -- $1
  $2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9...}
  (gdb) p $1
  $3 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
    20, 21, 22, 23, 24, <unavailable> <repeats 75 times>}
  (gdb)

Accesses with other languages work similarly, although for Ada only 
C-style [] array element/dimension accesses use history.  For both Ada 
and Fortran () array element/dimension accesses go straight to the 
inferior, bypassing the value history just as with C pointers.

Co-Authored-By: Maciej W. Rozycki <macro@embecosm.com>
---
Changes from v2:

- Adjust for the `value_copy' update in 1/5.

- Remove the handling of (dst_len != src_len) in `value_copy' where
  `dst_len' is always the same as `src_len' (from the corresponding 
  settings in `val' assigned to from `arg' right beforehand).

- Switch Ada and Fortran test cases to using `allow_ada_tests' and 
  `allow_fortran_tests' respectively.

- Fix a couple of formatting issues involving spaces used instead of tabs.

Changes from v1:

- Load `max-value-size' worth data into the value history for limited 
  length accesses and mark the area beyond unavailable.

- Handle the `output' command.

- Expand test coverage.
---
 gdb/NEWS                                     |    6 
 gdb/doc/gdb.texinfo                          |    9 
 gdb/f-valprint.c                             |   32 ++-
 gdb/printcmd.c                               |   16 +
 gdb/testsuite/gdb.ada/limited-length.exp     |  264 +++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/limited-length/foo.adb |   37 +++
 gdb/testsuite/gdb.ada/limited-length/pck.adb |   25 ++
 gdb/testsuite/gdb.ada/limited-length/pck.ads |   21 ++
 gdb/testsuite/gdb.base/limited-length.c      |   48 ++++
 gdb/testsuite/gdb.base/limited-length.exp    |  242 ++++++++++++++++++++++++
 gdb/testsuite/gdb.fortran/limited-length.exp |  220 ++++++++++++++++++++++
 gdb/testsuite/gdb.fortran/limited-length.f90 |   39 +++
 gdb/valprint.c                               |   10 -
 gdb/value.c                                  |  186 +++++++++++++++++--
 gdb/value.h                                  |   17 +
 15 files changed, 1147 insertions(+), 25 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ada/limited-length.exp
 create mode 100644 gdb/testsuite/gdb.ada/limited-length/foo.adb
 create mode 100644 gdb/testsuite/gdb.ada/limited-length/pck.adb
 create mode 100644 gdb/testsuite/gdb.ada/limited-length/pck.ads
 create mode 100644 gdb/testsuite/gdb.base/limited-length.c
 create mode 100644 gdb/testsuite/gdb.base/limited-length.exp
 create mode 100644 gdb/testsuite/gdb.fortran/limited-length.exp
 create mode 100644 gdb/testsuite/gdb.fortran/limited-length.f90

gdb-aburgess-limited-length-array.diff
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS
+++ src/gdb/NEWS
@@ -354,6 +354,12 @@ GDB now supports floating-point on Loong
   Disabling this can cause a performance penalty when there are a lot of
   symbols to load, but is useful for debugging purposes.
 
+* The 'set print elements' setting now helps when printing large arrays.
+  If an array would otherwise exceed max-value-size, but 'print elements'
+  is set such that the size of elements to print is less than or equal
+  to 'max-value-size', GDB will now still print the array, however only
+  'max-value-size' worth of data will be added into the value history.
+
 * New commands
 
 maint set backtrace-on-fatal-signal on|off
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo
+++ src/gdb/doc/gdb.texinfo
@@ -11756,6 +11756,14 @@ When @value{GDBN} starts, this limit is
 Setting @var{number-of-elements} to @code{unlimited} or zero means
 that the number of elements to print is unlimited.
 
+When printing very large arrays, whose size is greater than
+@code{max-value-size} (@pxref{set max-value-size,,max-value-size}),
+if the @code{print elements} is set such that the size of the elements
+being printed is less than or equal to @code{max-value-size}, then
+@value{GDBN} will print the array (up to the @code{print elements} limit),
+and only @code{max-value-size} worth of data will be added into the value
+history (@pxref{Value History, ,Value History}).
+
 @item show print elements
 Display the number of elements of a large array that @value{GDBN} will print.
 
@@ -14171,6 +14179,7 @@ may indicate a value that is incorrectly
 @value{GDBN} to try and allocate an overly large amount of memory.
 
 @table @code
+@anchor{set max-value-size}
 @kindex set max-value-size
 @item set max-value-size @var{bytes}
 @itemx set max-value-size unlimited
Index: src/gdb/f-valprint.c
===================================================================
--- src.orig/gdb/f-valprint.c
+++ src/gdb/f-valprint.c
@@ -261,10 +261,20 @@ class fortran_array_printer_impl : publi
     size_t dim_indx = m_dimension - 1;
     struct type *elt_type_prev = m_elt_type_prev;
     LONGEST elt_off_prev = m_elt_off_prev;
-    bool repeated = (m_options->repeat_count_threshold < UINT_MAX
-		     && elt_type_prev != nullptr
-		     && value_contents_eq (m_val, elt_off_prev, m_val, elt_off,
-					   elt_type->length ()));
+    bool repeated = false;
+
+    if (m_options->repeat_count_threshold < UINT_MAX
+	&& elt_type_prev != nullptr)
+      {
+	struct value *e_val = value_from_component (m_val, elt_type, elt_off);
+	struct value *e_prev = value_from_component (m_val, elt_type,
+						     elt_off_prev);
+	repeated = ((value_entirely_available (e_prev)
+		     && value_entirely_available (e_val)
+		     && value_contents_eq (e_prev, e_val))
+		    || (value_entirely_unavailable (e_prev)
+			&& value_entirely_unavailable (e_val)));
+      }
 
     if (repeated)
       m_nrepeats++;
@@ -333,7 +343,7 @@ class fortran_array_printer_impl : publi
      have been sliced and we do not want to compare any memory contents
      present between the slices requested.  */
   bool
-  dimension_contents_eq (const struct value *val, struct type *type,
+  dimension_contents_eq (struct value *val, struct type *type,
 			 LONGEST offset1, LONGEST offset2)
   {
     if (type->code () == TYPE_CODE_ARRAY
@@ -362,8 +372,16 @@ class fortran_array_printer_impl : publi
 	return true;
       }
     else
-      return value_contents_eq (val, offset1, val, offset2,
-				type->length ());
+      {
+	struct value *e_val1 = value_from_component (val, type, offset1);
+	struct value *e_val2 = value_from_component (val, type, offset2);
+
+	return ((value_entirely_available (e_val1)
+		 && value_entirely_available (e_val2)
+		 && value_contents_eq (e_val1, e_val2))
+		|| (value_entirely_unavailable (e_val1)
+		    && value_entirely_unavailable (e_val2)));
+      }
   }
 
   /* The number of elements printed so far.  */
Index: src/gdb/printcmd.c
===================================================================
--- src.orig/gdb/printcmd.c
+++ src/gdb/printcmd.c
@@ -1242,6 +1242,11 @@ print_command_parse_format (const char *
 void
 print_value (value *val, const value_print_options &opts)
 {
+  /* This setting allows large arrays to be printed by limiting the
+     number of elements that are loaded into GDB's memory; we only
+     need to load as many array elements as we plan to print.  */
+  scoped_array_length_limiting limit_large_arrays (opts.print_max);
+
   int histindex = record_latest_value (val);
 
   annotate_value_history_begin (histindex, value_type (val));
@@ -1301,6 +1306,11 @@ process_print_command_args (const char *
 
   if (exp != nullptr && *exp)
     {
+      /* This setting allows large arrays to be printed by limiting the
+	 number of elements that are loaded into GDB's memory; we only
+	 need to load as many array elements as we plan to print.  */
+      scoped_array_length_limiting limit_large_arrays (print_opts->print_max);
+
       /* VOIDPRINT is true to indicate that we do want to print a void
 	 value, so invert it for parse_expression.  */
       expression_up expr = parse_expression (exp, nullptr, !voidprint);
@@ -1489,6 +1499,12 @@ output_command (const char *exp, int fro
 
   get_formatted_print_options (&opts, format);
   opts.raw = fmt.raw;
+
+  /* This setting allows large arrays to be printed by limiting the
+     number of elements that are loaded into GDB's memory; we only
+     need to load as many array elements as we plan to print.  */
+  scoped_array_length_limiting limit_large_arrays (opts.print_max);
+
   print_formatted (val, fmt.size, &opts, gdb_stdout);
 
   annotate_value_end ();
Index: src/gdb/testsuite/gdb.ada/limited-length.exp
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.ada/limited-length.exp
@@ -0,0 +1,264 @@
+# Copyright 2023 Free Software Foundation, Inc.
+#
+# 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/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable \
+	[list debug ]] != "" } {
+  return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb]
+if {![runto "foo.adb:$bp_location"]} {
+    perror "Couldn't run ${testfile}"
+    return
+}
+
+with_test_prefix "with standard max-value size" {
+    gdb_test "print Large_1d_Array" \
+	" = \\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\
+	       13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\
+	       25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	       37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,\
+	       49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,\
+	       61, 62, 63, 64\\)"
+    gdb_test -nonl "output Large_1d_Array" \
+	"\\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\
+	    13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\
+	    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	    37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,\
+	    49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,\
+	    61, 62, 63, 64\\)"
+    gdb_test "print Large_3d_Array" \
+	" = \\(\\(\\(1, 2, 3, 4\\), \\(5, 6, 7, 8\\),\
+		  \\(9, 10, 11, 12\\), \\(13, 14, 15, 16\\)\\),\
+	       \\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+		  \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\),\
+	       \\(\\(33, 34, 35, 36\\), \\(37, 38, 39, 40\\),\
+		  \\(41, 42, 43, 44\\), \\(45, 46, 47, 48\\)\\),\
+	       \\(\\(49, 50, 51, 52\\), \\(53, 54, 55, 56\\),\
+		  \\(57, 58, 59, 60\\), \\(61, 62, 63, 64\\)\\)\\)"
+    gdb_test -nonl "output Large_3d_Array" \
+	"\\(\\(\\(1, 2, 3, 4\\), \\(5, 6, 7, 8\\),\
+	       \\(9, 10, 11, 12\\), \\(13, 14, 15, 16\\)\\),\
+	    \\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+	       \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\),\
+	    \\(\\(33, 34, 35, 36\\), \\(37, 38, 39, 40\\),\
+	       \\(41, 42, 43, 44\\), \\(45, 46, 47, 48\\)\\),\
+	    \\(\\(49, 50, 51, 52\\), \\(53, 54, 55, 56\\),\
+	       \\(57, 58, 59, 60\\), \\(61, 62, 63, 64\\)\\)\\)"
+}
+
+# Set the max-value-size so we can only print 33 elements.
+set elements 33
+set elem_size [get_valueof "/d" "(Large_1d_Array(1)'Size + 7) / 8" "*unknown*"]
+gdb_test_no_output "set max-value-size [expr $elem_size * $elements]"
+
+with_test_prefix "with reduced max-value size" {
+    gdb_test "print Large_1d_Array" \
+	"value of type `.*' requires $decimal bytes,\
+	 which is more than max-value-size"
+    gdb_test "output Large_1d_Array" \
+	"value of type `.*' requires $decimal bytes,\
+	 which is more than max-value-size"
+    gdb_test "print Large_3d_Array" \
+	"value of type `.*' requires $decimal bytes,\
+	 which is more than max-value-size"
+    gdb_test "output Large_3d_Array" \
+	"value of type `.*' requires $decimal bytes,\
+	 which is more than max-value-size"
+}
+
+with_test_prefix "with reduced print -elements flag" {
+    gdb_test "print -elements 2 -- Large_1d_Array" \
+	" = \\(1, 2\\.\\.\\.\\)"
+    gdb_test "print -elements 2 -- Large_3d_Array" \
+	" = \\(\\(\\(1, 2\\.\\.\\.\\), \\(5, 6\\.\\.\\.\\)\\.\\.\\.\\),\
+	       \\(\\(17, 18\\.\\.\\.\\),\
+		  \\(21, 22\\.\\.\\.\\)\\.\\.\\.\\)\\.\\.\\.\\)"
+}
+
+gdb_test_no_output "set print elements 2"
+
+with_test_prefix "with reduced print elements" {
+    gdb_test "print Large_1d_Array" \
+	" = \\(1, 2\\.\\.\\.\\)"
+    gdb_test -nonl "output Large_1d_Array" \
+	"\\(1, 2\\.\\.\\.\\)"
+
+    gdb_test "print \$" \
+	" = \\(1, 2\\.\\.\\.\\)" \
+	"print Large_1d_Array from history"
+    gdb_test -nonl "output \$\$" \
+	"\\(1, 2\\.\\.\\.\\)" \
+	"output Large_1d_Array from history"
+
+    gdb_test "print Large_3d_Array" \
+	" = \\(\\(\\(1, 2\\.\\.\\.\\), \\(5, 6\\.\\.\\.\\)\\.\\.\\.\\),\
+	       \\(\\(17, 18\\.\\.\\.\\),\
+		  \\(21, 22\\.\\.\\.\\)\\.\\.\\.\\)\\.\\.\\.\\)"
+    gdb_test -nonl "output Large_3d_Array" \
+	"\\(\\(\\(1, 2\\.\\.\\.\\), \\(5, 6\\.\\.\\.\\)\\.\\.\\.\\),\
+	    \\(\\(17, 18\\.\\.\\.\\),\
+	       \\(21, 22\\.\\.\\.\\)\\.\\.\\.\\)\\.\\.\\.\\)"
+
+    gdb_test "print \$" \
+	" = \\(\\(\\(1, 2\\.\\.\\.\\), \\(5, 6\\.\\.\\.\\)\\.\\.\\.\\),\
+	       \\(\\(17, 18\\.\\.\\.\\),\
+		  \\(21, 22\\.\\.\\.\\)\\.\\.\\.\\)\\.\\.\\.\\)" \
+	"print Large_3d_Array from history"
+    gdb_test -nonl "output \$\$" \
+	"\\(\\(\\(1, 2\\.\\.\\.\\), \\(5, 6\\.\\.\\.\\)\\.\\.\\.\\),\
+	    \\(\\(17, 18\\.\\.\\.\\),\
+	       \\(21, 22\\.\\.\\.\\)\\.\\.\\.\\)\\.\\.\\.\\)" \
+	"output Large_3d_Array from history"
+}
+
+gdb_test_no_output "set print elements $elements"
+
+with_test_prefix "with print elements matching max-value size" {
+    gdb_test "print \$\$2" \
+	" = \\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\
+	       13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\
+	       25, 26, 27, 28, 29, 30, 31, 32, 33\\.\\.\\.\\)" \
+	"print Large_1d_Array from history"
+    gdb_test -nonl "output \$\$3" \
+	"\\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\
+	    13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\
+	    25, 26, 27, 28, 29, 30, 31, 32, 33\\.\\.\\.\\)" \
+	"output Large_1d_Array from history"
+
+    gdb_test "print \$\$2" \
+	" = \\(\\(\\(1, 2, 3, 4\\), \\(5, 6, 7, 8\\),\
+		  \\(9, 10, 11, 12\\), \\(13, 14, 15, 16\\)\\),\
+	       \\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+		  \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\),\
+	       \\(\\(33(?:, <unavailable>)\{3\}\\)(?:,\
+		  \\(<unavailable>(?:, <unavailable>)\{3\}\\))\{3\}\\),\
+	       \\(\\(<unavailable>(?:, <unavailable>)\{3\}\\)(?:,\
+		  \\(<unavailable>(?:, <unavailable>)\{3\}\\))\{3\}\\)\\)" \
+	"print Large_3d_Array from history"
+    gdb_test -nonl "output \$\$3" \
+	"\\(\\(\\(1, 2, 3, 4\\), \\(5, 6, 7, 8\\),\
+	       \\(9, 10, 11, 12\\), \\(13, 14, 15, 16\\)\\),\
+	    \\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+	       \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\),\
+	    \\(\\(33(?:, <unavailable>)\{3\}\\)(?:,\
+	       \\(<unavailable>(?:, <unavailable>)\{3\}\\))\{3\}\\),\
+	    \\(\\(<unavailable>(?:, <unavailable>)\{3\}\\)(?:,\
+	       \\(<unavailable>(?:, <unavailable>)\{3\}\\))\{3\}\\)\\)" \
+	"output Large_3d_Array from history"
+}
+
+gdb_test_no_output "set max-value-size unlimited"
+gdb_test_no_output "set print elements unlimited"
+gdb_test_no_output "set print repeats 2"
+
+with_test_prefix "with unlimited print elements" {
+    gdb_test "print \$\$" \
+	" = \\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\
+	       13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\
+	       25, 26, 27, 28, 29, 30, 31, 32, 33,\
+	       <unavailable> <repeats 31 times>\\)" \
+	"print Large_1d_Array from history"
+    gdb_test -nonl "output \$\$2" \
+	"\\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\
+	    13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\
+	    25, 26, 27, 28, 29, 30, 31, 32, 33,\
+	    <unavailable> <repeats 31 times>\\)" \
+	"output Large_1d_Array from history"
+
+    gdb_test "print \$\$" \
+	" = \\(\\(\\(1, 2, 3, 4\\), \\(5, 6, 7, 8\\),\
+		  \\(9, 10, 11, 12\\), \\(13, 14, 15, 16\\)\\),\
+	       \\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+		  \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\),\
+	       \\(\\(33, <unavailable> <repeats 3 times>\\),\
+		  \\(<unavailable> <repeats 4 times>\\) <repeats 3 times>\\),\
+	       \\(\\(<unavailable> <repeats 4 times>\\)\
+		  <repeats 4 times>\\)\\)" \
+	"print Large_3d_Array from history"
+    gdb_test -nonl "output \$\$2" \
+	"\\(\\(\\(1, 2, 3, 4\\), \\(5, 6, 7, 8\\),\
+	       \\(9, 10, 11, 12\\), \\(13, 14, 15, 16\\)\\),\
+	    \\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+	       \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\),\
+	    \\(\\(33, <unavailable> <repeats 3 times>\\),\
+	       \\(<unavailable> <repeats 4 times>\\) <repeats 3 times>\\),\
+	    \\(\\(<unavailable> <repeats 4 times>\\) <repeats 4 times>\\)\\)" \
+	"output Large_3d_Array from history"
+
+    gdb_test "print \$\[2\]" \
+	" = \\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+	       \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\)" \
+	"print available Large_3d_Array row from history"
+    gdb_test -nonl "output \$\$\[2\]" \
+	"\\(\\(17, 18, 19, 20\\), \\(21, 22, 23, 24\\),\
+	    \\(25, 26, 27, 28\\), \\(29, 30, 31, 32\\)\\)" \
+	"output available Large_3d_Array row from history"
+
+    gdb_test "print \$\$\[3\]" \
+	" = \\(\\(33, <unavailable> <repeats 3 times>\\),\
+	       \\(<unavailable> <repeats 4 times>\\) <repeats 3 times>\\)" \
+	"print partially available Large_3d_Array row from history"
+    gdb_test -nonl "output \$\$2\[3\]" \
+	"\\(\\(33, <unavailable> <repeats 3 times>\\),\
+	    \\(<unavailable> <repeats 4 times>\\) <repeats 3 times>\\)" \
+	"output partially available Large_3d_Array row from history"
+
+    # These go straigth to the inferior.
+    gdb_test "print \$\$2(3)" \
+	" = \\(\\(33, 34, 35, 36\\), \\(37, 38, 39, 40\\),\
+	       \\(41, 42, 43, 44\\), \\(45, 46, 47, 48\\)\\)" \
+	"print partially available Large_3d_Array row bypassing history"
+    gdb_test -nonl "output \$\$3(3)" \
+	"\\(\\(33, 34, 35, 36\\), \\(37, 38, 39, 40\\),\
+	    \\(41, 42, 43, 44\\), \\(45, 46, 47, 48\\)\\)" \
+	"output partially available Large_3d_Array row bypassing history"
+
+    gdb_test "print \$\$3\[4\]" \
+	" = <unavailable>" \
+	"print unavailable Large_3d_Array row from history"
+    gdb_test -nonl "output \$\$4\[4\]" \
+	"<unavailable>" \
+	"output unavailable Large_3d_Array row from history"
+
+    gdb_test "print \$\$4\[3\]\[1\]\[1\]" \
+	" = 33" \
+	"print available Large_3d_Array element from history"
+    gdb_test -nonl "output \$\$5\[3\]\[1\]\[1\]" \
+	"33" \
+	"output available Large_3d_Array element from history"
+
+    gdb_test "print \$\$5\[3\]\[1\]\[2\]" \
+	" = <unavailable>" \
+	"print unavailable Large_3d_Array element from history"
+    gdb_test -nonl "output \$\$6\[3\]\[1\]\[2\]" \
+	"<unavailable>" \
+	"output unavailable Large_3d_Array element from history"
+
+    gdb_test "print \$\$6\[3\]\[1\]\[1\] + \$\$6\[3\]\[1\]\[2\]" \
+	"value is not available" \
+	"print expression referring unavailable element from history"
+    gdb_test "output \$\$6\[3\]\[1\]\[1\] + \$\$6\[3\]\[1\]\[2\]" \
+	"value is not available" \
+	"output expression referring unavailable element from history"
+}
Index: src/gdb/testsuite/gdb.ada/limited-length/foo.adb
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.ada/limited-length/foo.adb
@@ -0,0 +1,37 @@
+--  This testcase is part of GDB, the GNU debugger.
+--
+--  Copyright 2023 Free Software Foundation, Inc.
+--
+--  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/>.
+
+with Pck; use Pck;
+
+procedure Foo is
+   Large_1d_Array : array (1..64) of Integer;
+   Large_3d_Array : array (1..4,1..4,1..4) of Integer;
+   Count : Integer := 1;
+begin
+   for i in 1 .. 4 loop
+     for j in 1 .. 4 loop
+        for k in 1 .. 4 loop
+           Large_1d_Array (Count) := Count;
+           Large_3d_Array (i,j,k) := Count;
+           Count := Count + 1;
+        end loop;
+     end loop;
+   end loop;
+   Do_Nothing (Large_1d_Array'Address);
+   Do_Nothing (Large_3d_Array'Address); -- STOP
+end Foo;
+
Index: src/gdb/testsuite/gdb.ada/limited-length/pck.adb
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.ada/limited-length/pck.adb
@@ -0,0 +1,25 @@
+--  This testcase is part of GDB, the GNU debugger.
+--
+--  Copyright 2023 Free Software Foundation, Inc.
+--
+--  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/>.
+
+package body Pck is
+
+   procedure Do_Nothing (A : System.Address) is
+   begin
+      null;
+   end Do_Nothing;
+
+end Pck;
Index: src/gdb/testsuite/gdb.ada/limited-length/pck.ads
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.ada/limited-length/pck.ads
@@ -0,0 +1,21 @@
+--  This testcase is part of GDB, the GNU debugger.
+--
+--  Copyright 2023 Free Software Foundation, Inc.
+--
+--  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/>.
+
+with System;
+package Pck is
+   procedure Do_Nothing (A : System.Address);
+end Pck;
Index: src/gdb/testsuite/gdb.base/limited-length.c
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.base/limited-length.c
@@ -0,0 +1,48 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   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/>.  */
+
+int large_1d_array[] = {
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+  20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+  30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+  40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+  50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+  60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+  70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+  80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+  90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+};
+
+int large_2d_array[][10] = {
+  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+  {10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
+  {20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
+  {30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
+  {40, 41, 42, 43, 44, 45, 46, 47, 48, 49},
+  {50, 51, 52, 53, 54, 55, 56, 57, 58, 59},
+  {60, 61, 62, 63, 64, 65, 66, 67, 68, 69},
+  {70, 71, 72, 73, 74, 75, 76, 77, 78, 79},
+  {80, 81, 82, 83, 84, 85, 86, 87, 88, 89},
+  {90, 91, 92, 93, 94, 95, 96, 97, 98, 99}
+};
+
+int
+main ()
+{
+  return 0;
+}
Index: src/gdb/testsuite/gdb.base/limited-length.exp
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.base/limited-length.exp
@@ -0,0 +1,242 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Test GDB's limited array printing.
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
+    return -1
+}
+
+if {![runto_main]} {
+    perror "couldn't run to breakpoint"
+    continue
+}
+
+with_test_prefix "with standard max-value size" {
+    gdb_test "print large_1d_array" \
+	" = \\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\
+		12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\
+		24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\
+		36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\
+		48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\
+		60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\
+		72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,\
+		84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
+		96, 97, 98, 99\\\}"
+    gdb_test -nonl "output large_1d_array" \
+	"\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\
+	     12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\
+	     24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\
+	     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\
+	     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\
+	     60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,\
+	     72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,\
+	     84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
+	     96, 97, 98, 99\\\}"
+    gdb_test "print large_2d_array" \
+	" = \\\{\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\\},\
+		\\\{10, 11, 12, 13, 14, 15, 16, 17, 18, 19\\\},\
+		\\\{20, 21, 22, 23, 24, 25, 26, 27, 28, 29\\\},\
+		\\\{30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\\},\
+		\\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\},\
+		\\\{50, 51, 52, 53, 54, 55, 56, 57, 58, 59\\\},\
+		\\\{60, 61, 62, 63, 64, 65, 66, 67, 68, 69\\\},\
+		\\\{70, 71, 72, 73, 74, 75, 76, 77, 78, 79\\\},\
+		\\\{80, 81, 82, 83, 84, 85, 86, 87, 88, 89\\\},\
+		\\\{90, 91, 92, 93, 94, 95, 96, 97, 98, 99\\\}\\\}"
+    gdb_test -nonl "output large_2d_array" \
+	"\\\{\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\\},\
+	     \\\{10, 11, 12, 13, 14, 15, 16, 17, 18, 19\\\},\
+	     \\\{20, 21, 22, 23, 24, 25, 26, 27, 28, 29\\\},\
+	     \\\{30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\\},\
+	     \\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\},\
+	     \\\{50, 51, 52, 53, 54, 55, 56, 57, 58, 59\\\},\
+	     \\\{60, 61, 62, 63, 64, 65, 66, 67, 68, 69\\\},\
+	     \\\{70, 71, 72, 73, 74, 75, 76, 77, 78, 79\\\},\
+	     \\\{80, 81, 82, 83, 84, 85, 86, 87, 88, 89\\\},\
+	     \\\{90, 91, 92, 93, 94, 95, 96, 97, 98, 99\\\}\\\}"
+}
+
+# Set the max-value-size so we can only print 51 elements.
+set elements 51
+set int_size [get_valueof "/d" "sizeof(large_1d_array\[0\])" "*unknown*"]
+gdb_test_no_output "set max-value-size [expr $int_size * $elements]"
+
+with_test_prefix "with reduced max-value size" {
+    gdb_test "print large_1d_array" \
+	"\r\nvalue requires $decimal bytes, which is more than max-value-size"
+    gdb_test "output large_1d_array" \
+	"\r\nvalue requires $decimal bytes, which is more than max-value-size"
+    gdb_test "print large_2d_array" \
+	"\r\nvalue requires $decimal bytes, which is more than max-value-size"
+    gdb_test "output large_2d_array" \
+	"\r\nvalue requires $decimal bytes, which is more than max-value-size"
+}
+
+gdb_test_no_output "set print elements 3"
+
+with_test_prefix "with reduced print elements" {
+    gdb_test "print large_1d_array" \
+	" = \\\{0, 1, 2\\.\\.\\.\\\}"
+    gdb_test -nonl "output large_1d_array" \
+	"\\\{0, 1, 2\\.\\.\\.\\\}"
+
+    gdb_test "print \$" \
+	" = \\\{0, 1, 2\\.\\.\\.\\\}" \
+	"print large_1d_array from history"
+    gdb_test -nonl "output \$\$" \
+	"\\\{0, 1, 2\\.\\.\\.\\\}" \
+	"output large_1d_array from history"
+
+    gdb_test "print large_2d_array" \
+	" = \\\{\\\{0, 1, 2\\.\\.\\.\\\}, \\\{10, 11, 12\\.\\.\\.\\\},\
+	    \\\{20, 21, 22\\.\\.\\.\\\}\\.\\.\\.\\\}"
+    gdb_test -nonl "output large_2d_array" \
+	"\\\{\\\{0, 1, 2\\.\\.\\.\\\}, \\\{10, 11, 12\\.\\.\\.\\\},\
+	 \\\{20, 21, 22\\.\\.\\.\\\}\\.\\.\\.\\\}"
+
+    gdb_test "print \$" \
+	" = \\\{\\\{0, 1, 2\\.\\.\\.\\\}, \\\{10, 11, 12\\.\\.\\.\\\},\
+	    \\\{20, 21, 22\\.\\.\\.\\\}\\.\\.\\.\\\}" \
+	"print large_2d_array from history"
+    gdb_test -nonl "output \$\$" \
+	"\\\{\\\{0, 1, 2\\.\\.\\.\\\}, \\\{10, 11, 12\\.\\.\\.\\\},\
+	 \\\{20, 21, 22\\.\\.\\.\\\}\\.\\.\\.\\\}" \
+	"output large_2d_array from history"
+}
+
+gdb_test_no_output "set print elements $elements"
+
+with_test_prefix "with print elements matching max-value size" {
+    gdb_test "print \$\$2" \
+	" = \\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\
+		12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\
+		24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\
+		36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\
+		48, 49, 50\\.\\.\\.\\\}" \
+	"print large_1d_array from history"
+    gdb_test -nonl "output \$\$3" \
+	"\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\
+	     12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\
+	     24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\
+	     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\
+	     48, 49, 50\\.\\.\\.\\\}" \
+	"output large_1d_array from history"
+
+    gdb_test "print \$\$2" \
+	" = \\\{\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\\},\
+		\\\{10, 11, 12, 13, 14, 15, 16, 17, 18, 19\\\},\
+		\\\{20, 21, 22, 23, 24, 25, 26, 27, 28, 29\\\},\
+		\\\{30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\\},\
+		\\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\},\
+		\\\{50(?:, <unavailable>)\{9\}\\\}(?:,\
+		\\\{<unavailable>(?:, <unavailable>)\{9\}\\\})\{4\}\\\}" \
+	"print large_2d_array from history"
+    gdb_test -nonl "output \$\$3" \
+	"\\\{\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\\},\
+	     \\\{10, 11, 12, 13, 14, 15, 16, 17, 18, 19\\\},\
+	     \\\{20, 21, 22, 23, 24, 25, 26, 27, 28, 29\\\},\
+	     \\\{30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\\},\
+	     \\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\},\
+	     \\\{50(?:, <unavailable>)\{9\}\\\}(?:,\
+	     \\\{<unavailable>(?:, <unavailable>)\{9\}\\\})\{4\}\\\}" \
+	"output large_2d_array from history"
+}
+
+gdb_test_no_output "set max-value-size unlimited"
+gdb_test_no_output "set print elements unlimited"
+gdb_test_no_output "set print repeats 3"
+
+with_test_prefix "with unlimited print elements" {
+    gdb_test "print \$\$" \
+	" = \\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\
+		12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\
+		24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\
+		36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\
+		48, 49, 50, <unavailable> <repeats 49 times>\\\}" \
+	"print large_1d_array from history"
+    gdb_test -nonl "output \$\$2" \
+	"\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\
+	     12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,\
+	     24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\
+	     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\
+	     48, 49, 50, <unavailable> <repeats 49 times>\\\}" \
+	"output large_1d_array from history"
+
+    gdb_test "print \$\$" \
+	" = \\\{\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\\},\
+		\\\{10, 11, 12, 13, 14, 15, 16, 17, 18, 19\\\},\
+		\\\{20, 21, 22, 23, 24, 25, 26, 27, 28, 29\\\},\
+		\\\{30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\\},\
+		\\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\},\
+		\\\{50, <unavailable> <repeats 9 times>\\\},\
+		\\\{<unavailable> <repeats 10 times>\\\}\
+		<repeats 4 times>\\\}" \
+	"print large_2d_array from history"
+    gdb_test -nonl "output \$\$2" \
+	"\\\{\\\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\\},\
+	     \\\{10, 11, 12, 13, 14, 15, 16, 17, 18, 19\\\},\
+	     \\\{20, 21, 22, 23, 24, 25, 26, 27, 28, 29\\\},\
+	     \\\{30, 31, 32, 33, 34, 35, 36, 37, 38, 39\\\},\
+	     \\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\},\
+	     \\\{50, <unavailable> <repeats 9 times>\\\},\
+	     \\\{<unavailable> <repeats 10 times>\\\}\
+	     <repeats 4 times>\\\}" \
+	"output large_2d_array from history"
+
+    gdb_test "print \$\[4\]" \
+	" = \\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\}" \
+	"print available large_2d_array row from history"
+    gdb_test -nonl "output \$\$\[4\]" \
+	"\\\{40, 41, 42, 43, 44, 45, 46, 47, 48, 49\\\}" \
+	"output available large_2d_array row from history"
+
+    gdb_test "print \$\$\[5\]" \
+	" = \\\{50, <unavailable> <repeats 9 times>\\\}" \
+	"print partially available large_2d_array row from history"
+    gdb_test -nonl "output \$\$2\[5\]" \
+	"\\\{50, <unavailable> <repeats 9 times>\\\}" \
+	"output partially available large_2d_array row from history"
+
+    gdb_test "print \$\$2\[6\]" \
+	" = <unavailable>" \
+	"print unavailable large_2d_array row from history"
+    gdb_test -nonl "output \$\$3\[6\]" \
+	"<unavailable>" \
+	"output unavailable large_2d_array row from history"
+
+    gdb_test "print \$\$3\[5\]\[0\]" \
+	" = 50" \
+	"print available large_2d_array element from history"
+    gdb_test -nonl "output \$\$4\[5\]\[0\]" \
+	"50" \
+	"output available large_2d_array element from history"
+
+    gdb_test "print \$\$4\[5\]\[1\]" \
+	" = <unavailable>" \
+	"print unavailable large_2d_array element from history"
+    gdb_test -nonl "output \$\$5\[5\]\[1\]" \
+	"<unavailable>" \
+	"output unavailable large_2d_array element from history"
+
+    gdb_test "print \$\$5\[5\]\[0\] + \$\$5\[5\]\[1\]" \
+	"value is not available" \
+	"print expression referring unavailable element from history"
+    gdb_test "output \$\$5\[5\]\[0\] + \$\$5\[5\]\[1\]" \
+	"value is not available" \
+	"output expression referring unavailable element from history"
+}
Index: src/gdb/testsuite/gdb.fortran/limited-length.exp
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.fortran/limited-length.exp
@@ -0,0 +1,220 @@
+# Copyright 2023 Free Software Foundation, Inc.
+#
+# 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/>.
+
+# This file tests GDB's limited length array printing.
+
+load_lib "fortran.exp"
+
+require allow_fortran_tests
+
+standard_testfile .f90
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug f90}]} {
+    return -1
+}
+
+if {![fortran_runto_main]} {
+    perror "Could not run to main."
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "Break Here"]
+gdb_continue_to_breakpoint "stop-here" ".*Break Here.*"
+
+with_test_prefix "with standard max-value size" {
+    gdb_test "print large_4d_array" \
+	" = \\(\\(\\(\\(1, 2, 3\\) \\(4, 5, 6\\) \\(7, 8, 9\\)\\)\
+		  \\(\\(10, 11, 12\\) \\(13, 14, 15\\) \\(16, 17, 18\\)\\)\
+		  \\(\\(19, 20, 21\\) \\(22, 23, 24\\) \\(25, 26, 27\\)\\)\\)\
+	       \\(\\(\\(28, 29, 30\\) \\(31, 32, 33\\) \\(34, 35, 36\\)\\)\
+		  \\(\\(37, 38, 39\\) \\(40, 41, 42\\) \\(43, 44, 45\\)\\)\
+		  \\(\\(46, 47, 48\\) \\(49, 50, 51\\) \\(52, 53, 54\\)\\)\\)\
+	       \\(\\(\\(55, 56, 57\\) \\(58, 59, 60\\) \\(61, 62, 63\\)\\)\
+		  \\(\\(64, 65, 66\\) \\(67, 68, 69\\) \\(70, 71, 72\\)\\)\
+		  \\(\\(73, 74, 75\\) \\(76, 77, 78\\)\
+		     \\(79, 80, 81\\)\\)\\)\\)"
+    gdb_test -nonl "output large_4d_array" \
+	"\\(\\(\\(\\(1, 2, 3\\) \\(4, 5, 6\\) \\(7, 8, 9\\)\\)\
+	       \\(\\(10, 11, 12\\) \\(13, 14, 15\\) \\(16, 17, 18\\)\\)\
+	       \\(\\(19, 20, 21\\) \\(22, 23, 24\\) \\(25, 26, 27\\)\\)\\)\
+	    \\(\\(\\(28, 29, 30\\) \\(31, 32, 33\\) \\(34, 35, 36\\)\\)\
+	       \\(\\(37, 38, 39\\) \\(40, 41, 42\\) \\(43, 44, 45\\)\\)\
+	       \\(\\(46, 47, 48\\) \\(49, 50, 51\\) \\(52, 53, 54\\)\\)\\)\
+	    \\(\\(\\(55, 56, 57\\) \\(58, 59, 60\\) \\(61, 62, 63\\)\\)\
+	       \\(\\(64, 65, 66\\) \\(67, 68, 69\\) \\(70, 71, 72\\)\\)\
+	       \\(\\(73, 74, 75\\) \\(76, 77, 78\\) \\(79, 80, 81\\)\\)\\)\\)"
+    gdb_test "print large_1d_array" \
+	" = \\(1, 2, 3, 4, 5, 6, 7, 8, 9,\
+	       10, 11, 12, 13, 14, 15, 16, 17, 18,\
+	       19, 20, 21, 22, 23, 24, 25, 26, 27,\
+	       28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	       37, 38, 39, 40, 41, 42, 43, 44, 45,\
+	       46, 47, 48, 49, 50, 51, 52, 53, 54,\
+	       55, 56, 57, 58, 59, 60, 61, 62, 63,\
+	       64, 65, 66, 67, 68, 69, 70, 71, 72,\
+	       73, 74, 75, 76, 77, 78, 79, 80, 81\\)"
+    gdb_test -nonl "output large_1d_array" \
+	"\\(1, 2, 3, 4, 5, 6, 7, 8, 9,\
+	    10, 11, 12, 13, 14, 15, 16, 17, 18,\
+	    19, 20, 21, 22, 23, 24, 25, 26, 27,\
+	    28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	    37, 38, 39, 40, 41, 42, 43, 44, 45,\
+	    46, 47, 48, 49, 50, 51, 52, 53, 54,\
+	    55, 56, 57, 58, 59, 60, 61, 62, 63,\
+	    64, 65, 66, 67, 68, 69, 70, 71, 72,\
+	    73, 74, 75, 76, 77, 78, 79, 80, 81\\)"
+}
+
+# Set the max-value-size so we can only print 50 elements.
+set elements 50
+set elem_size [get_valueof "/d" "sizeof(large_1d_array(1))" "*unknown*"]
+gdb_test_no_output "set max-value-size [expr $elem_size * $elements]"
+
+with_test_prefix "with reduced max-value size" {
+    gdb_test "print large_4d_array" \
+	"value requires $decimal bytes, which is more than max-value-size"
+    gdb_test "output large_4d_array" \
+	"value requires $decimal bytes, which is more than max-value-size"
+    gdb_test "print large_1d_array" \
+	"value requires $decimal bytes, which is more than max-value-size"
+    gdb_test "output large_1d_array" \
+	"value requires $decimal bytes, which is more than max-value-size"
+}
+
+with_test_prefix "with reduced print -elements flag" {
+    gdb_test "print -elements 5 -- large_4d_array" \
+	" = \\(\\(\\(\\(1, 2, 3\\) \\(4, 5, \\.\\.\\.\\)\
+		     \\.\\.\\.\\) \\.\\.\\.\\) \\.\\.\\.\\)"
+    gdb_test "print -elements 5 -- large_1d_array" \
+	" = \\(1, 2, 3, 4, 5, \\.\\.\\.\\)"
+}
+
+gdb_test_no_output "set print elements 5"
+
+with_test_prefix "with reduced print elements" {
+    gdb_test "print large_4d_array" \
+	" = \\(\\(\\(\\(1, 2, 3\\) \\(4, 5, \\.\\.\\.\\)\
+		     \\.\\.\\.\\) \\.\\.\\.\\) \\.\\.\\.\\)"
+    gdb_test -nonl "output large_4d_array" \
+	"\\(\\(\\(\\(1, 2, 3\\) \\(4, 5, \\.\\.\\.\\)\
+		  \\.\\.\\.\\) \\.\\.\\.\\) \\.\\.\\.\\)"
+
+    gdb_test "print \$" \
+	" = \\(\\(\\(\\(1, 2, 3\\) \\(4, 5, \\.\\.\\.\\)\
+		     \\.\\.\\.\\) \\.\\.\\.\\) \\.\\.\\.\\)" \
+	"print large_4d_array from history"
+    gdb_test -nonl "output \$\$" \
+	"\\(\\(\\(\\(1, 2, 3\\) \\(4, 5, \\.\\.\\.\\)\
+		  \\.\\.\\.\\) \\.\\.\\.\\) \\.\\.\\.\\)" \
+	"output large_4d_array from history"
+
+    gdb_test "print large_1d_array" \
+	" = \\(1, 2, 3, 4, 5, \\.\\.\\.\\)"
+    gdb_test -nonl "output large_1d_array" \
+	"\\(1, 2, 3, 4, 5, \\.\\.\\.\\)"
+
+    gdb_test "print \$" \
+	" = \\(1, 2, 3, 4, 5, \\.\\.\\.\\)" \
+	"print large_1d_array from history"
+    gdb_test -nonl "output \$\$" \
+	"\\(1, 2, 3, 4, 5, \\.\\.\\.\\)" \
+	"output large_1d_array from history"
+}
+
+gdb_test_no_output "set print elements $elements"
+
+with_test_prefix "with print elements matching max-value size" {
+    gdb_test "print \$\$2" \
+	" = \\(\\(\\(\\(1, 2, 3\\) \\(4, 5, 6\\) \\(7, 8, 9\\)\\)\
+		  \\(\\(10, 11, 12\\) \\(13, 14, 15\\) \\(16, 17, 18\\)\\)\
+		  \\(\\(19, 20, 21\\) \\(22, 23, 24\\) \\(25, 26, 27\\)\\)\\)\
+	       \\(\\(\\(28, 29, 30\\) \\(31, 32, 33\\) \\(34, 35, 36\\)\\)\
+		  \\(\\(37, 38, 39\\) \\(40, 41, 42\\) \\(43, 44, 45\\)\\)\
+		  \\(\\(46, 47, 48\\) \\(49, 50, \\.\\.\\.\\) \\.\\.\\.\\)\\)\
+	       \\.\\.\\.\\)" \
+	"print large_4d_array from history"
+    gdb_test -nonl "output \$\$3" \
+	"\\(\\(\\(\\(1, 2, 3\\) \\(4, 5, 6\\) \\(7, 8, 9\\)\\)\
+	       \\(\\(10, 11, 12\\) \\(13, 14, 15\\) \\(16, 17, 18\\)\\)\
+	       \\(\\(19, 20, 21\\) \\(22, 23, 24\\) \\(25, 26, 27\\)\\)\\)\
+	    \\(\\(\\(28, 29, 30\\) \\(31, 32, 33\\) \\(34, 35, 36\\)\\)\
+	       \\(\\(37, 38, 39\\) \\(40, 41, 42\\) \\(43, 44, 45\\)\\)\
+	       \\(\\(46, 47, 48\\) \\(49, 50, \\.\\.\\.\\) \\.\\.\\.\\)\\)\
+	    \\.\\.\\.\\)" \
+	"output large_4d_array from history"
+
+    gdb_test "print \$\$2" \
+	" = \\(1, 2, 3, 4, 5, 6, 7, 8, 9,\
+	       10, 11, 12, 13, 14, 15, 16, 17, 18,\
+	       19, 20, 21, 22, 23, 24, 25, 26, 27,\
+	       28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	       37, 38, 39, 40, 41, 42, 43, 44, 45,\
+	       46, 47, 48, 49, 50, \\.\\.\\.\\)" \
+	"print large_1d_array from history"
+    gdb_test -nonl "output \$\$2" \
+	"\\(1, 2, 3, 4, 5, 6, 7, 8, 9,\
+	    10, 11, 12, 13, 14, 15, 16, 17, 18,\
+	    19, 20, 21, 22, 23, 24, 25, 26, 27,\
+	    28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	    37, 38, 39, 40, 41, 42, 43, 44, 45,\
+	    46, 47, 48, 49, 50, \\.\\.\\.\\)" \
+	"output large_1d_array from history"
+}
+
+gdb_test_no_output "set max-value-size unlimited"
+gdb_test_no_output "set print elements unlimited"
+gdb_test_no_output "set print repeats 2"
+
+with_test_prefix "with unlimited print elements" {
+    gdb_test "print \$\$" \
+	" = \\(\\(\\(\\(1, 2, 3\\) \\(4, 5, 6\\) \\(7, 8, 9\\)\\)\
+		  \\(\\(10, 11, 12\\) \\(13, 14, 15\\) \\(16, 17, 18\\)\\)\
+		  \\(\\(19, 20, 21\\) \\(22, 23, 24\\) \\(25, 26, 27\\)\\)\\)\
+	       \\(\\(\\(28, 29, 30\\) \\(31, 32, 33\\) \\(34, 35, 36\\)\\)\
+		  \\(\\(37, 38, 39\\) \\(40, 41, 42\\) \\(43, 44, 45\\)\\)\
+		  \\(\\(46, 47, 48\\) \\(49, 50, <unavailable>\\)\
+		     \\(<unavailable>, <repeats 3 times>\\)\\)\\)\
+	       \\(\\(\\(<unavailable>, <repeats 3 times>\\)\
+		     <repeats 3 times>\\) <repeats 3 times>\\)\\)" \
+	"print large_4d_array from history"
+    gdb_test -nonl "output \$\$2" \
+	"\\(\\(\\(\\(1, 2, 3\\) \\(4, 5, 6\\) \\(7, 8, 9\\)\\)\
+	       \\(\\(10, 11, 12\\) \\(13, 14, 15\\) \\(16, 17, 18\\)\\)\
+	       \\(\\(19, 20, 21\\) \\(22, 23, 24\\) \\(25, 26, 27\\)\\)\\)\
+	    \\(\\(\\(28, 29, 30\\) \\(31, 32, 33\\) \\(34, 35, 36\\)\\)\
+	       \\(\\(37, 38, 39\\) \\(40, 41, 42\\) \\(43, 44, 45\\)\\)\
+	       \\(\\(46, 47, 48\\) \\(49, 50, <unavailable>\\)\
+		  \\(<unavailable>, <repeats 3 times>\\)\\)\\)\
+	    \\(\\(\\(<unavailable>, <repeats 3 times>\\)\
+		  <repeats 3 times>\\) <repeats 3 times>\\)\\)" \
+	"output large_4d_array from history"
+
+    gdb_test "print \$\$" \
+	" = \\(1, 2, 3, 4, 5, 6, 7, 8, 9,\
+	       10, 11, 12, 13, 14, 15, 16, 17, 18,\
+	       19, 20, 21, 22, 23, 24, 25, 26, 27,\
+	       28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	       37, 38, 39, 40, 41, 42, 43, 44, 45,\
+	       46, 47, 48, 49, 50, <unavailable>, <repeats 31 times>\\)" \
+	"print large_1d_array from history"
+    gdb_test -nonl "output \$\$2" \
+	"\\(1, 2, 3, 4, 5, 6, 7, 8, 9,\
+	    10, 11, 12, 13, 14, 15, 16, 17, 18,\
+	    19, 20, 21, 22, 23, 24, 25, 26, 27,\
+	    28, 29, 30, 31, 32, 33, 34, 35, 36,\
+	    37, 38, 39, 40, 41, 42, 43, 44, 45,\
+	    46, 47, 48, 49, 50, <unavailable>, <repeats 31 times>\\)" \
+	"output large_1d_array from history"
+}
Index: src/gdb/testsuite/gdb.fortran/limited-length.f90
===================================================================
--- /dev/null
+++ src/gdb/testsuite/gdb.fortran/limited-length.f90
@@ -0,0 +1,39 @@
+! This testcase is part of GDB, the GNU debugger.
+!
+! Copyright 2023 Free Software Foundation, Inc.
+!
+! 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 2 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/>.
+
+program main
+  integer(kind=8), dimension (3, 3, 3, 3) :: large_4d_array = reshape ((/ &
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, &
+       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, &
+       33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, &
+       48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, &
+       63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, &
+       78, 79, 80, 81/), (/3, 3, 3, 3/))
+
+  integer(kind=8), dimension (81) :: large_1d_array = reshape ((/ &
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, &
+       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, &
+       33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, &
+       48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, &
+       63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, &
+       78, 79, 80, 81/), (/81/))
+
+  print *, ""
+  print *, ""	! Break Here
+  print *, large_4d_array
+  print *, large_1d_array
+end program main
Index: src/gdb/valprint.c
===================================================================
--- src.orig/gdb/valprint.c
+++ src/gdb/valprint.c
@@ -2018,13 +2018,21 @@ value_print_array_elements (struct value
 	 UINT_MAX (unlimited).  */
       if (options->repeat_count_threshold < UINT_MAX)
 	{
+	  bool unavailable = value_entirely_unavailable (element);
+	  bool available = value_entirely_available (element);
+
 	  while (rep1 < len)
 	    {
 	      struct value *rep_elt
 		= value_from_component_bitsize (val, elttype,
 						rep1 * bit_stride,
 						bit_stride);
-	      if (!value_contents_eq (element, rep_elt))
+	      bool repeated = ((available
+				&& value_entirely_available (rep_elt)
+				&& value_contents_eq (element, rep_elt))
+			       || (unavailable
+				   && value_entirely_unavailable (rep_elt)));
+	      if (!repeated)
 		break;
 	      ++reps;
 	      ++rep1;
Index: src/gdb/value.c
===================================================================
--- src.orig/gdb/value.c
+++ src/gdb/value.c
@@ -369,6 +369,14 @@ struct value
      treated pretty much the same, except not-saved registers have a
      different string representation and related error strings.  */
   std::vector<range> optimized_out;
+
+  /* This is only non-zero for values of TYPE_CODE_ARRAY and if the size of
+     the array in inferior memory is greater than max_value_size.  If these
+     conditions are met then, when the value is loaded from the inferior
+     GDB will only load a portion of the array into memory, and
+     limited_length will be set to indicate the length in octets that were
+     loaded from the inferior.  */
+  ULONGEST limited_length = 0;
 };
 
 /* See value.h.  */
@@ -1046,6 +1054,93 @@ check_type_length_before_alloc (const st
     }
 }
 
+/* When this has a value, it is used to limit the number of array elements
+   of an array that are loaded into memory when an array value is made
+   non-lazy.  */
+static gdb::optional<int> array_length_limiting_element_count;
+
+/* See value.h.  */
+scoped_array_length_limiting::scoped_array_length_limiting (int elements)
+{
+  m_old_value = array_length_limiting_element_count;
+  array_length_limiting_element_count.emplace (elements);
+}
+
+/* See value.h.  */
+scoped_array_length_limiting::~scoped_array_length_limiting ()
+{
+  array_length_limiting_element_count = m_old_value;
+}
+
+/* Find the inner element type for ARRAY_TYPE.  */
+
+static struct type *
+find_array_element_type (struct type *array_type)
+{
+  array_type = check_typedef (array_type);
+  gdb_assert (array_type->code () == TYPE_CODE_ARRAY);
+
+  if (current_language->la_language == language_fortran)
+    while (array_type->code () == TYPE_CODE_ARRAY)
+      {
+	array_type = array_type->target_type ();
+	array_type = check_typedef (array_type);
+      }
+  else
+    {
+      array_type = array_type->target_type ();
+      array_type = check_typedef (array_type);
+    }
+
+  return array_type;
+}
+
+/* Return the limited length of ARRAY_TYPE, which must be of
+   TYPE_CODE_ARRAY.  This function can only be called when the global
+   ARRAY_LENGTH_LIMITING_ELEMENT_COUNT has a value.
+
+   The limited length of an array is the smallest of either (1) the total
+   size of the array type, or (2) the array target type multiplies by the
+   array_length_limiting_element_count.  */
+
+static ULONGEST
+calculate_limited_array_length (struct type *array_type)
+{
+  gdb_assert (array_length_limiting_element_count.has_value ());
+
+  array_type = check_typedef (array_type);
+  gdb_assert (array_type->code () == TYPE_CODE_ARRAY);
+
+  struct type *elm_type = find_array_element_type (array_type);
+  ULONGEST len = (elm_type->length ()
+		  * (*array_length_limiting_element_count));
+  len = std::min (len, array_type->length ());
+
+  return len;
+}
+
+/* Try to limit ourselves to only fetching the limited number of
+   elements.  However, if this limited number of elements still
+   puts us over max_value_size, then we still throw an error.  */
+
+static bool
+set_limited_array_length (struct value *val)
+{
+  ULONGEST limit = val->limited_length;
+  ULONGEST len = value_type (val)->length ();
+
+  if (array_length_limiting_element_count.has_value ())
+    len = calculate_limited_array_length (value_type (val));
+
+  if (limit != 0 && len > limit)
+    len = limit;
+  if (len > max_value_size)
+    return false;
+
+  val->limited_length = max_value_size;
+  return true;
+}
+
 /* Allocate the contents of VAL if it has not been allocated yet.
    If CHECK_SIZE is true, then apply the usual max-value-size checks.  */
 
@@ -1054,10 +1149,26 @@ allocate_value_contents (struct value *v
 {
   if (!val->contents)
     {
+      struct type *enclosing_type = value_enclosing_type (val);
+      ULONGEST len = enclosing_type->length ();
+
       if (check_size)
-	check_type_length_before_alloc (val->enclosing_type);
-      val->contents.reset
-	((gdb_byte *) xzalloc (val->enclosing_type->length ()));
+	{
+	  /* If we are allocating the contents of an array, which
+	     is greater in size than max_value_size, and there is
+	     an element limit in effect, then we can possibly try
+	     to load only a sub-set of the array contents into
+	     GDB's memory.  */
+	  if (value_type (val) == enclosing_type
+	      && value_type (val)->code () == TYPE_CODE_ARRAY
+	      && len > max_value_size
+	      && set_limited_array_length (val))
+	    len = val->limited_length;
+	  else
+	    check_type_length_before_alloc (enclosing_type);
+	}
+
+      val->contents.reset ((gdb_byte *) xzalloc (len));
     }
 }
 
@@ -1786,10 +1897,7 @@ value_copy (const value *arg)
   struct type *encl_type = value_enclosing_type (arg);
   struct value *val;
 
-  if (value_lazy (arg))
-    val = allocate_value_lazy (encl_type);
-  else
-    val = allocate_value (encl_type, false);
+  val = allocate_value_lazy (encl_type);
   val->type = arg->type;
   VALUE_LVAL (val) = arg->lval;
   val->location = arg->location;
@@ -1805,17 +1913,28 @@ value_copy (const value *arg)
   val->initialized = arg->initialized;
   val->unavailable = arg->unavailable;
   val->optimized_out = arg->optimized_out;
+  val->parent = arg->parent;
+  val->limited_length = arg->limited_length;
 
-  if (!value_lazy (val) && !value_entirely_optimized_out (val))
+  if (!value_lazy (val)
+      && !(value_entirely_optimized_out (val)
+	   || value_entirely_unavailable (val)))
     {
+      ULONGEST length = val->limited_length;
+      if (length == 0)
+	length = value_enclosing_type (val)->length ();
+
       gdb_assert (arg->contents != nullptr);
-      ULONGEST length = value_enclosing_type (arg)->length ();
       const auto &arg_view
 	= gdb::make_array_view (arg->contents.get (), length);
-      copy (arg_view, value_contents_all_raw (val));
+
+      allocate_value_contents (val, false);
+      gdb::array_view<gdb_byte> val_contents
+	= value_contents_all_raw (val).slice (0, length);
+
+      copy (arg_view, val_contents);
     }
 
-  val->parent = arg->parent;
   if (VALUE_LVAL (val) == lval_computed)
     {
       const struct lval_funcs *funcs = val->location.computed.funcs;
@@ -1949,20 +2068,40 @@ set_value_component_location (struct val
 int
 record_latest_value (struct value *val)
 {
+  struct type *enclosing_type = value_enclosing_type (val);
+  struct type *type = value_type (val);
+
   /* We don't want this value to have anything to do with the inferior anymore.
      In particular, "set $1 = 50" should not affect the variable from which
      the value was taken, and fast watchpoints should be able to assume that
      a value on the value history never changes.  */
   if (value_lazy (val))
-    value_fetch_lazy (val);
+    {
+      /* We know that this is a _huge_ array, any attempt to fetch this
+	 is going to cause GDB to throw an error.  However, to allow
+	 the array to still be displayed we fetch its contents up to
+	 `max_value_size' and mark anything beyond "unavailable" in
+	 the history.  */
+      if (type->code () == TYPE_CODE_ARRAY
+	  && type->length () > max_value_size
+	  && array_length_limiting_element_count.has_value ()
+	  && enclosing_type == type
+	  && calculate_limited_array_length (type) <= max_value_size)
+	val->limited_length = max_value_size;
+
+      value_fetch_lazy (val);
+    }
 
   /* Don't pretend we have anything available there in the history beyond
      the boundaries of the value recorded.  It's not like inferior memory
      where there is actual stuff underneath.  */
-  ULONGEST length = value_enclosing_type (val)->length ();
+  ULONGEST length = enclosing_type->length ();
   mark_value_bits_unavailable (val, LONGEST_MIN, 0 ^ LONGEST_MIN);
   mark_value_bits_unavailable (val, length * TARGET_CHAR_BIT,
 			       LONGEST_MAX - length * TARGET_CHAR_BIT);
+  if (val->limited_length != 0)
+    mark_value_bytes_unavailable (val, val->limited_length,
+				  length - val->limited_length);
 
   /* We preserve VALUE_LVAL so that the user can find out where it was fetched
      from.  This is a bit dubious, because then *&$1 does not just return $1
@@ -4059,10 +4198,23 @@ value_fetch_lazy_memory (struct value *v
   CORE_ADDR addr = value_address (val);
   struct type *type = check_typedef (value_enclosing_type (val));
 
-  if (type->length ())
-      read_value_memory (val, 0, value_stack (val),
-			 addr, value_contents_all_raw (val).data (),
-			 type_length_units (type));
+  /* Figure out how much we should copy from memory.  Usually, this is just
+     the size of the type, but, for arrays, we might only be loading a
+     small part of the array (this is only done for very large arrays).  */
+  int len = 0;
+  if (val->limited_length > 0)
+    {
+      gdb_assert (value_type (val)->code () == TYPE_CODE_ARRAY);
+      len = val->limited_length;
+    }
+  else if (type->length () > 0)
+    len = type_length_units (type);
+
+  gdb_assert (len >= 0);
+
+  if (len > 0)
+    read_value_memory (val, 0, value_stack (val), addr,
+		       value_contents_all_raw (val).data (), len);
 }
 
 /* Helper for value_fetch_lazy when the value is in a register.  */
Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h
+++ src/gdb/value.h
@@ -1235,4 +1235,21 @@ extern void finalize_values ();
    of floating-point, fixed-point, or integer type.  */
 extern gdb_mpq value_to_gdb_mpq (struct value *value);
 
+/* While an instance of this class is live, and array values that are
+   created, that are larger than max_value_size, will be restricted in size
+   to a particular number of elements.  */
+
+struct scoped_array_length_limiting
+{
+  /* Limit any large array values to only contain ELEMENTS elements.  */
+  scoped_array_length_limiting (int elements);
+
+  /* Restore the previous array value limit.  */
+  ~scoped_array_length_limiting ();
+
+private:
+  /* Used to hold the previous array value element limit.  */
+  gdb::optional<int> m_old_value;
+};
+
 #endif /* !defined (VALUE_H) */

  parent reply	other threads:[~2023-01-23 23:14 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-23 23:00 [PATCH v3 0/5] gdb: introduce " Maciej W. Rozycki
2023-01-23 23:13 ` [PATCH v3 1/5] GDB: Ignore `max-value-size' setting with value history accesses Maciej W. Rozycki
2023-01-31 17:58   ` Tom Tromey
2023-02-10 14:17     ` Maciej W. Rozycki
2023-01-23 23:13 ` [PATCH v3 2/5] GDB: Fix the mess with value byte/bit range types Maciej W. Rozycki
2023-01-31 18:09   ` Tom Tromey
2023-02-10 14:18     ` Maciej W. Rozycki
2023-02-10 14:49       ` Tom Tromey
2023-01-23 23:14 ` [PATCH v3 3/5] GDB: Only make data actually retrieved into value history available Maciej W. Rozycki
2023-01-31 18:47   ` Tom Tromey
2023-02-10 14:18     ` Maciej W. Rozycki
2023-02-10 21:11       ` Tom Tromey
2023-01-23 23:14 ` [PATCH v3 4/5] GDB/testsuite: Add `-nonl' option to `gdb_test' Maciej W. Rozycki
2023-01-31 19:02   ` Tom Tromey
2023-01-23 23:14 ` Maciej W. Rozycki [this message]
2023-01-24 12:59   ` [PATCH v3 5/5] GDB: Introduce limited array lengths while printing values Eli Zaretskii
2023-01-31 20:49   ` Tom Tromey
2023-02-10 14:18     ` Maciej W. Rozycki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.DEB.2.20.2301211719580.7841@tpp.orcam.me.uk \
    --to=macro@embecosm.com \
    --cc=Richard.Bunt@arm.com \
    --cc=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).