GDB: Introduce limited array lengths while printing values

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>
This commit is contained in:
Andrew Burgess 2023-02-10 23:49:19 +00:00 committed by Maciej W. Rozycki
parent a2fb245a4b
commit a0c0791577
15 changed files with 1149 additions and 24 deletions

View File

@ -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 ]

View File

@ -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

View File

@ -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. */

View File

@ -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 ();

View File

@ -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"
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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

View File

@ -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;

View File

@ -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<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. */
@ -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<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 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<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;
@ -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. */

View File

@ -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<int> m_old_value;
};
#endif /* !defined (VALUE_H) */