diff --git a/gdb/NEWS b/gdb/NEWS
index b85923cf80d..1328f4faa80 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -44,6 +44,12 @@
keyword already gave an error when used multiple times with the
watch command, this remains unchanged.
+* 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
maintenance print record-instruction [ N ]
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7b128053b5a..0beb45857c3 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -11759,6 +11759,14 @@ When @value{GDBN} starts, this limit is set to 200.
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.
@@ -14174,6 +14182,7 @@ may indicate a value that is incorrectly large, this in turn may cause
@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
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
index 55dbcc8309f..b08613f9153 100644
--- a/gdb/f-valprint.c
+++ b/gdb/f-valprint.c
@@ -261,10 +261,20 @@ public:
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 @@ private:
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 @@ private:
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. */
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 7f3551327a8..9bda60d6f80 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1242,6 +1242,11 @@ print_command_parse_format (const char **expp, const char *cmdname,
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 *args, value_print_options *print_opts,
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 from_tty)
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 ();
diff --git a/gdb/testsuite/gdb.ada/limited-length.exp b/gdb/testsuite/gdb.ada/limited-length.exp
new file mode 100644
index 00000000000..1e3afe72c7e
--- /dev/null
+++ b/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 .
+
+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(?:, )\{3\}\\)(?:,\
+ \\((?:, )\{3\}\\))\{3\}\\),\
+ \\(\\((?:, )\{3\}\\)(?:,\
+ \\((?:, )\{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(?:, )\{3\}\\)(?:,\
+ \\((?:, )\{3\}\\))\{3\}\\),\
+ \\(\\((?:, )\{3\}\\)(?:,\
+ \\((?:, )\{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,\
+ \\)" \
+ "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,\
+ \\)" \
+ "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, \\),\
+ \\( \\) \\),\
+ \\(\\( \\)\
+ \\)\\)" \
+ "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, \\),\
+ \\( \\) \\),\
+ \\(\\( \\) \\)\\)" \
+ "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, \\),\
+ \\( \\) \\)" \
+ "print partially available Large_3d_Array row from history"
+ gdb_test -nonl "output \$\$2\[3\]" \
+ "\\(\\(33, \\),\
+ \\( \\) \\)" \
+ "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\]" \
+ " = " \
+ "print unavailable Large_3d_Array row from history"
+ gdb_test -nonl "output \$\$4\[4\]" \
+ "" \
+ "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\]" \
+ " = " \
+ "print unavailable Large_3d_Array element from history"
+ gdb_test -nonl "output \$\$6\[3\]\[1\]\[2\]" \
+ "" \
+ "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"
+}
diff --git a/gdb/testsuite/gdb.ada/limited-length/foo.adb b/gdb/testsuite/gdb.ada/limited-length/foo.adb
new file mode 100644
index 00000000000..b9505446655
--- /dev/null
+++ b/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 .
+
+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;
+
diff --git a/gdb/testsuite/gdb.ada/limited-length/pck.adb b/gdb/testsuite/gdb.ada/limited-length/pck.adb
new file mode 100644
index 00000000000..53443027df9
--- /dev/null
+++ b/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 .
+
+package body Pck is
+
+ procedure Do_Nothing (A : System.Address) is
+ begin
+ null;
+ end Do_Nothing;
+
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/limited-length/pck.ads b/gdb/testsuite/gdb.ada/limited-length/pck.ads
new file mode 100644
index 00000000000..2ef2f6c9bdb
--- /dev/null
+++ b/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 .
+
+with System;
+package Pck is
+ procedure Do_Nothing (A : System.Address);
+end Pck;
diff --git a/gdb/testsuite/gdb.base/limited-length.c b/gdb/testsuite/gdb.base/limited-length.c
new file mode 100644
index 00000000000..177400d3894
--- /dev/null
+++ b/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 . */
+
+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;
+}
diff --git a/gdb/testsuite/gdb.base/limited-length.exp b/gdb/testsuite/gdb.base/limited-length.exp
new file mode 100644
index 00000000000..2918b1a1fe9
--- /dev/null
+++ b/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 .
+
+# 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(?:, )\{9\}\\\}(?:,\
+ \\\{(?:, )\{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(?:, )\{9\}\\\}(?:,\
+ \\\{(?:, )\{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, \\\}" \
+ "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, \\\}" \
+ "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, \\\},\
+ \\\{ \\\}\
+ \\\}" \
+ "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, \\\},\
+ \\\{ \\\}\
+ \\\}" \
+ "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, \\\}" \
+ "print partially available large_2d_array row from history"
+ gdb_test -nonl "output \$\$2\[5\]" \
+ "\\\{50, \\\}" \
+ "output partially available large_2d_array row from history"
+
+ gdb_test "print \$\$2\[6\]" \
+ " = " \
+ "print unavailable large_2d_array row from history"
+ gdb_test -nonl "output \$\$3\[6\]" \
+ "" \
+ "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\]" \
+ " = " \
+ "print unavailable large_2d_array element from history"
+ gdb_test -nonl "output \$\$5\[5\]\[1\]" \
+ "" \
+ "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"
+}
diff --git a/gdb/testsuite/gdb.fortran/limited-length.exp b/gdb/testsuite/gdb.fortran/limited-length.exp
new file mode 100644
index 00000000000..b7e43587421
--- /dev/null
+++ b/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 .
+
+# 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, \\)\
+ \\(, \\)\\)\\)\
+ \\(\\(\\(, \\)\
+ \\) \\)\\)" \
+ "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, \\)\
+ \\(, \\)\\)\\)\
+ \\(\\(\\(, \\)\
+ \\) \\)\\)" \
+ "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, , \\)" \
+ "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"
+}
diff --git a/gdb/testsuite/gdb.fortran/limited-length.f90 b/gdb/testsuite/gdb.fortran/limited-length.f90
new file mode 100644
index 00000000000..4b8568e1925
--- /dev/null
+++ b/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 .
+
+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
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 04f83f5194a..fe376c25e98 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -2018,13 +2018,21 @@ value_print_array_elements (struct value *val, struct ui_file *stream,
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;
diff --git a/gdb/value.c b/gdb/value.c
index fbdb07959c6..4be408e6870 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -373,6 +373,14 @@ struct value
treated pretty much the same, except not-saved registers have a
different string representation and related error strings. */
std::vector 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. */
@@ -1053,6 +1061,94 @@ check_type_length_before_alloc (const struct type *type)
}
}
+/* 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 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 refuse it and
+ return failure here, which will ultimately 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. */
@@ -1061,10 +1157,26 @@ allocate_value_contents (struct value *val, bool check_size)
{
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));
}
}
@@ -1791,10 +1903,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;
@@ -1811,17 +1920,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 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;
@@ -1955,12 +2075,34 @@ set_value_component_location (struct value *component,
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);
+ }
+
+ ULONGEST limit = val->limited_length;
+ if (limit != 0)
+ mark_value_bytes_unavailable (val, limit,
+ enclosing_type->length () - limit);
/* Mark the value as recorded in the history for the availability check. */
val->in_history = true;
@@ -4060,10 +4202,23 @@ value_fetch_lazy_memory (struct value *val)
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. */
diff --git a/gdb/value.h b/gdb/value.h
index 80f92597d07..c002ad09b45 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -1228,4 +1228,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 m_old_value;
+};
+
#endif /* !defined (VALUE_H) */