From patchwork Thu Jan 12 09:02:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 63092 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D0B5A385B800 for ; Thu, 12 Jan 2023 09:02:58 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by sourceware.org (Postfix) with ESMTPS id 89895385439F for ; Thu, 12 Jan 2023 09:02:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 89895385439F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-lf1-x12b.google.com with SMTP id cf42so27499140lfb.1 for ; Thu, 12 Jan 2023 01:02:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=mime-version:user-agent:references:message-id:in-reply-to:subject :cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=8YyuAwoYafdNPICIDhn1IL+ri5Q91UPNn8gT9wHw38w=; b=NhtXb39dIbcvJ2+PsHWjZznERUbr7fZLW0+cqHPvSDsYpyVzfnFkAn3YqfucE0R6Dt nazp21L+2r7uDP62Ydik7Iq7oB+3b7OkobIuKdKGHTAEv3gseSJWHzy4VkQRRd9sE46+ yxuLhWs00LIhMQD4WVw1futEig+96uU1qkSplH+lImJeyi+STDVc56CzQfUOVxUM4DeX UuFJOMjwVJYZRsbsJVI2rzCxPtvrhRjkedFHDUaEI5v8xlrc1sd/1TOkJkkfFxcje7tO N8CN5n5zBzU/Ud+FzWNMzWMytrE4QZ4O9tNzKXMNODZcDhfL/e20lRBnUcTho+qEeK2Q UL7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:references:message-id:in-reply-to:subject :cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=8YyuAwoYafdNPICIDhn1IL+ri5Q91UPNn8gT9wHw38w=; b=iou9RmYJGu7IA854sQ4ePStO6G9ifpQffvNPJpN3/q6T97ahkXDIDcEMA0HVd+/CBC N3aiC6Seo41hB/fyf5pXDeqlE8IGNX+uAx/0z8/SlCTKGuygPj3M/QRkadkbB0CoZZ7g 6Tupg2zL0cIsio32oWlBYjjYtbKm5CXN5SNVofrNTxrJcw4upi/2YuJjMfWnEJ4t+2GC Jm+u9RP+Ucgstw4W+bfQ2onRScXLxj/wINIl3WOyS06nT1CgpoC2hsmPQA7W96vwoRaJ c38PoYvubSGQliEUw7spSjWVGMZBcp7S4wXRRKqdwMp2sqUfJ+71Mpf2I2K1ERm8E403 FxPQ== X-Gm-Message-State: AFqh2kpjr0sbViC22IYHoC1KmIlQ6DaHsuYO6eia0/XSB36O7Js0+ZIP QqMOidSrA3TQIXT1dn9lsvse1c/M08iyliGT X-Google-Smtp-Source: AMrXdXv3W8XVyE2OdO0BKjOBPW78MlaezPjXtfmZr3HgkATOVnh9EndoeKqXvIcsjN2PFC2+4sMvsQ== X-Received: by 2002:a19:f513:0:b0:4c5:a0b4:336b with SMTP id j19-20020a19f513000000b004c5a0b4336bmr2973927lfb.1.1673514149659; Thu, 12 Jan 2023 01:02:29 -0800 (PST) Received: from [192.168.219.3] ([78.8.192.131]) by smtp.gmail.com with ESMTPSA id o13-20020ac24e8d000000b004a25bb4494fsm3161266lfr.178.2023.01.12.01.02.24 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Jan 2023 01:02:29 -0800 (PST) Date: Thu, 12 Jan 2023 09:02:23 +0000 (GMT) From: "Maciej W. Rozycki" To: gdb-patches@sourceware.org cc: Andrew Burgess , Tom Tromey , Richard Bunt Subject: [PATCH v2 5/5] GDB: Introduce limited array lengths while printing values In-Reply-To: Message-ID: References: User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 X-Spam-Status: No, score=1.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SCC_10_SHORT_WORD_LINES, SCC_20_SHORT_WORD_LINES, SCC_35_SHORT_WORD_LINES, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=no autolearn_force=no version=3.4.6 X-Spam-Level: * X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" From: Andrew Burgess 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, } (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 --- Changes from v1: - Load `max-value-size' worth data into the value history for limited length accesses and mark the area beyond unavailable. - Handle the `output' command. - Expand test coverage. --- gdb/NEWS | 6 gdb/doc/gdb.texinfo | 9 gdb/f-valprint.c | 32 ++- gdb/printcmd.c | 16 + gdb/testsuite/gdb.ada/limited-length.exp | 266 +++++++++++++++++++++++++++ gdb/testsuite/gdb.ada/limited-length/foo.adb | 37 +++ gdb/testsuite/gdb.ada/limited-length/pck.adb | 25 ++ gdb/testsuite/gdb.ada/limited-length/pck.ads | 21 ++ gdb/testsuite/gdb.base/limited-length.c | 48 ++++ gdb/testsuite/gdb.base/limited-length.exp | 242 ++++++++++++++++++++++++ gdb/testsuite/gdb.fortran/limited-length.exp | 222 ++++++++++++++++++++++ gdb/testsuite/gdb.fortran/limited-length.f90 | 39 +++ gdb/valprint.c | 10 - gdb/value.c | 201 ++++++++++++++++++-- gdb/value.h | 17 + 15 files changed, 1165 insertions(+), 26 deletions(-) create mode 100644 gdb/testsuite/gdb.ada/limited-length.exp create mode 100644 gdb/testsuite/gdb.ada/limited-length/foo.adb create mode 100644 gdb/testsuite/gdb.ada/limited-length/pck.adb create mode 100644 gdb/testsuite/gdb.ada/limited-length/pck.ads create mode 100644 gdb/testsuite/gdb.base/limited-length.c create mode 100644 gdb/testsuite/gdb.base/limited-length.exp create mode 100644 gdb/testsuite/gdb.fortran/limited-length.exp create mode 100644 gdb/testsuite/gdb.fortran/limited-length.f90 gdb-aburgess-limited-length-array.diff Index: src/gdb/NEWS =================================================================== --- src.orig/gdb/NEWS +++ src/gdb/NEWS @@ -354,6 +354,12 @@ GDB now supports floating-point on Loong Disabling this can cause a performance penalty when there are a lot of symbols to load, but is useful for debugging purposes. +* The 'set print elements' setting now helps when printing large arrays. + If an array would otherwise exceed max-value-size, but 'print elements' + is set such that the number of elements to print is less than or equal + to 'max-value-size', GDB will now still print the array, however only + 'max-value-size' worth of data will be added into the value history. + * New commands maint set backtrace-on-fatal-signal on|off Index: src/gdb/doc/gdb.texinfo =================================================================== --- src.orig/gdb/doc/gdb.texinfo +++ src/gdb/doc/gdb.texinfo @@ -11756,6 +11756,14 @@ When @value{GDBN} starts, this limit is Setting @var{number-of-elements} to @code{unlimited} or zero means that the number of elements to print is unlimited. +When printing very large arrays, whose size is greater than +@code{max-value-size} (@pxref{set max-value-size,,max-value-size}), +if the @code{print elements} is set such that the size of the elements +being printed is less than or equal to @code{max-value-size}, then +@value{GDBN} will print the array (up to the @code{print elements} limit), +and only @code{max-value-size} worth of data will be added into the value +history (@pxref{Value History, ,Value History}). + @item show print elements Display the number of elements of a large array that @value{GDBN} will print. @@ -14171,6 +14179,7 @@ may indicate a value that is incorrectly @value{GDBN} to try and allocate an overly large amount of memory. @table @code +@anchor{set max-value-size} @kindex set max-value-size @item set max-value-size @var{bytes} @itemx set max-value-size unlimited Index: src/gdb/f-valprint.c =================================================================== --- src.orig/gdb/f-valprint.c +++ src/gdb/f-valprint.c @@ -261,10 +261,20 @@ class fortran_array_printer_impl : publi size_t dim_indx = m_dimension - 1; struct type *elt_type_prev = m_elt_type_prev; LONGEST elt_off_prev = m_elt_off_prev; - bool repeated = (m_options->repeat_count_threshold < UINT_MAX - && elt_type_prev != nullptr - && value_contents_eq (m_val, elt_off_prev, m_val, elt_off, - elt_type->length ())); + bool repeated = false; + + if (m_options->repeat_count_threshold < UINT_MAX + && elt_type_prev != nullptr) + { + struct value *e_val = value_from_component (m_val, elt_type, elt_off); + struct value *e_prev = value_from_component (m_val, elt_type, + elt_off_prev); + repeated = ((value_entirely_available (e_prev) + && value_entirely_available (e_val) + && value_contents_eq (e_prev, e_val)) + || (value_entirely_unavailable (e_prev) + && value_entirely_unavailable (e_val))); + } if (repeated) m_nrepeats++; @@ -333,7 +343,7 @@ class fortran_array_printer_impl : publi have been sliced and we do not want to compare any memory contents present between the slices requested. */ bool - dimension_contents_eq (const struct value *val, struct type *type, + dimension_contents_eq (struct value *val, struct type *type, LONGEST offset1, LONGEST offset2) { if (type->code () == TYPE_CODE_ARRAY @@ -362,8 +372,16 @@ class fortran_array_printer_impl : publi return true; } else - return value_contents_eq (val, offset1, val, offset2, - type->length ()); + { + struct value *e_val1 = value_from_component (val, type, offset1); + struct value *e_val2 = value_from_component (val, type, offset2); + + return ((value_entirely_available (e_val1) + && value_entirely_available (e_val2) + && value_contents_eq (e_val1, e_val2)) + || (value_entirely_unavailable (e_val1) + && value_entirely_unavailable (e_val2))); + } } /* The number of elements printed so far. */ Index: src/gdb/printcmd.c =================================================================== --- src.orig/gdb/printcmd.c +++ src/gdb/printcmd.c @@ -1242,6 +1242,11 @@ print_command_parse_format (const char * void print_value (value *val, const value_print_options &opts) { + /* This setting allows large arrays to be printed by limiting the + number of elements that are loaded into GDB's memory; we only + need to load as many array elements as we plan to print. */ + scoped_array_length_limiting limit_large_arrays (opts.print_max); + int histindex = record_latest_value (val); annotate_value_history_begin (histindex, value_type (val)); @@ -1301,6 +1306,11 @@ process_print_command_args (const char * if (exp != nullptr && *exp) { + /* This setting allows large arrays to be printed by limiting the + number of elements that are loaded into GDB's memory; we only + need to load as many array elements as we plan to print. */ + scoped_array_length_limiting limit_large_arrays (print_opts->print_max); + /* VOIDPRINT is true to indicate that we do want to print a void value, so invert it for parse_expression. */ expression_up expr = parse_expression (exp, nullptr, !voidprint); @@ -1489,6 +1499,12 @@ output_command (const char *exp, int fro get_formatted_print_options (&opts, format); opts.raw = fmt.raw; + + /* This setting allows large arrays to be printed by limiting the + number of elements that are loaded into GDB's memory; we only + need to load as many array elements as we plan to print. */ + scoped_array_length_limiting limit_large_arrays (opts.print_max); + print_formatted (val, fmt.size, &opts, gdb_stdout); annotate_value_end (); Index: src/gdb/testsuite/gdb.ada/limited-length.exp =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.ada/limited-length.exp @@ -0,0 +1,266 @@ +# 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" + +if {[skip_ada_tests]} { + return -1 +} + +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" +} Index: src/gdb/testsuite/gdb.ada/limited-length/foo.adb =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.ada/limited-length/foo.adb @@ -0,0 +1,37 @@ +-- This testcase is part of GDB, the GNU debugger. +-- +-- Copyright 2023 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +with Pck; use Pck; + +procedure Foo is + Large_1d_Array : array (1..64) of Integer; + Large_3d_Array : array (1..4,1..4,1..4) of Integer; + Count : Integer := 1; +begin + for i in 1 .. 4 loop + for j in 1 .. 4 loop + for k in 1 .. 4 loop + Large_1d_Array (Count) := Count; + Large_3d_Array (i,j,k) := Count; + Count := Count + 1; + end loop; + end loop; + end loop; + Do_Nothing (Large_1d_Array'Address); + Do_Nothing (Large_3d_Array'Address); -- STOP +end Foo; + Index: src/gdb/testsuite/gdb.ada/limited-length/pck.adb =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.ada/limited-length/pck.adb @@ -0,0 +1,25 @@ +-- This testcase is part of GDB, the GNU debugger. +-- +-- Copyright 2023 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +package body Pck is + + procedure Do_Nothing (A : System.Address) is + begin + null; + end Do_Nothing; + +end Pck; Index: src/gdb/testsuite/gdb.ada/limited-length/pck.ads =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.ada/limited-length/pck.ads @@ -0,0 +1,21 @@ +-- This testcase is part of GDB, the GNU debugger. +-- +-- Copyright 2023 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +with System; +package Pck is + procedure Do_Nothing (A : System.Address); +end Pck; Index: src/gdb/testsuite/gdb.base/limited-length.c =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.base/limited-length.c @@ -0,0 +1,48 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright (C) 2023 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +int large_1d_array[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 +}; + +int large_2d_array[][10] = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, + {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}, + {30, 31, 32, 33, 34, 35, 36, 37, 38, 39}, + {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}, + {50, 51, 52, 53, 54, 55, 56, 57, 58, 59}, + {60, 61, 62, 63, 64, 65, 66, 67, 68, 69}, + {70, 71, 72, 73, 74, 75, 76, 77, 78, 79}, + {80, 81, 82, 83, 84, 85, 86, 87, 88, 89}, + {90, 91, 92, 93, 94, 95, 96, 97, 98, 99} +}; + +int +main () +{ + return 0; +} Index: src/gdb/testsuite/gdb.base/limited-length.exp =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.base/limited-length.exp @@ -0,0 +1,242 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# 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" +} Index: src/gdb/testsuite/gdb.fortran/limited-length.exp =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.fortran/limited-length.exp @@ -0,0 +1,222 @@ +# 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" + +if {[skip_fortran_tests]} { + continue +} + +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" +} Index: src/gdb/testsuite/gdb.fortran/limited-length.f90 =================================================================== --- /dev/null +++ src/gdb/testsuite/gdb.fortran/limited-length.f90 @@ -0,0 +1,39 @@ +! This testcase is part of GDB, the GNU debugger. +! +! Copyright 2023 Free Software Foundation, Inc. +! +! This program is free software; you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation; either version 2 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program. If not, see . + +program main + integer(kind=8), dimension (3, 3, 3, 3) :: large_4d_array = reshape ((/ & + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, & + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, & + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, & + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, & + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, & + 78, 79, 80, 81/), (/3, 3, 3, 3/)) + + integer(kind=8), dimension (81) :: large_1d_array = reshape ((/ & + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, & + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, & + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, & + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, & + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, & + 78, 79, 80, 81/), (/81/)) + + print *, "" + print *, "" ! Break Here + print *, large_4d_array + print *, large_1d_array +end program main Index: src/gdb/valprint.c =================================================================== --- src.orig/gdb/valprint.c +++ src/gdb/valprint.c @@ -2018,13 +2018,21 @@ value_print_array_elements (struct value UINT_MAX (unlimited). */ if (options->repeat_count_threshold < UINT_MAX) { + bool unavailable = value_entirely_unavailable (element); + bool available = value_entirely_available (element); + while (rep1 < len) { struct value *rep_elt = value_from_component_bitsize (val, elttype, rep1 * bit_stride, bit_stride); - if (!value_contents_eq (element, rep_elt)) + bool repeated = ((available + && value_entirely_available (rep_elt) + && value_contents_eq (element, rep_elt)) + || (unavailable + && value_entirely_unavailable (rep_elt))); + if (!repeated) break; ++reps; ++rep1; Index: src/gdb/value.c =================================================================== --- src.orig/gdb/value.c +++ src/gdb/value.c @@ -369,6 +369,14 @@ struct value treated pretty much the same, except not-saved registers have a different string representation and related error strings. */ std::vector optimized_out; + + /* This is only non-zero for values of TYPE_CODE_ARRAY and if the size of + the array in inferior memory is greater than max_value_size. If these + conditions are met then, when the value is loaded from the inferior + GDB will only load a portion of the array into memory, and + limited_length will be set to indicate the length in octets that were + loaded from the inferior. */ + ULONGEST limited_length = 0; }; /* See value.h. */ @@ -1046,6 +1054,93 @@ check_type_length_before_alloc (const st } } +/* When this has a value, it is used to limit the number of array elements + of an array that are loaded into memory when an array value is made + non-lazy. */ +static gdb::optional array_length_limiting_element_count; + +/* See value.h. */ +scoped_array_length_limiting::scoped_array_length_limiting (int elements) +{ + m_old_value = array_length_limiting_element_count; + array_length_limiting_element_count.emplace (elements); +} + +/* See value.h. */ +scoped_array_length_limiting::~scoped_array_length_limiting () +{ + array_length_limiting_element_count = m_old_value; +} + +/* Find the inner element type for ARRAY_TYPE. */ + +static struct type * +find_array_element_type (struct type *array_type) +{ + array_type = check_typedef (array_type); + gdb_assert (array_type->code () == TYPE_CODE_ARRAY); + + if (current_language->la_language == language_fortran) + while (array_type->code () == TYPE_CODE_ARRAY) + { + array_type = array_type->target_type (); + array_type = check_typedef (array_type); + } + else + { + array_type = array_type->target_type (); + array_type = check_typedef (array_type); + } + + return array_type; +} + +/* Return the limited length of ARRAY_TYPE, which must be of + TYPE_CODE_ARRAY. This function can only be called when the global + ARRAY_LENGTH_LIMITING_ELEMENT_COUNT has a value. + + The limited length of an array is the smallest of either (1) the total + size of the array type, or (2) the array target type multiplies by the + array_length_limiting_element_count. */ + +static ULONGEST +calculate_limited_array_length (struct type *array_type) +{ + gdb_assert (array_length_limiting_element_count.has_value ()); + + array_type = check_typedef (array_type); + gdb_assert (array_type->code () == TYPE_CODE_ARRAY); + + struct type *elm_type = find_array_element_type (array_type); + ULONGEST len = (elm_type->length () + * (*array_length_limiting_element_count)); + len = std::min (len, array_type->length ()); + + return len; +} + +/* Try to limit ourselves to only fetching the limited number of + elements. However, if this limited number of elements still + puts us over max_value_size, then we still throw an error. */ + +static bool +set_limited_array_length (struct value *val) +{ + ULONGEST limit = val->limited_length; + ULONGEST len = value_type (val)->length (); + + if (array_length_limiting_element_count.has_value ()) + len = calculate_limited_array_length (value_type (val)); + + if (limit != 0 && len > limit) + len = limit; + if (len > max_value_size) + return false; + + val->limited_length = max_value_size; + return true; +} + /* Allocate the contents of VAL if it has not been allocated yet. If CHECK_SIZE is true, then apply the usual max-value-size checks. */ @@ -1054,10 +1149,26 @@ allocate_value_contents (struct value *v { if (!val->contents) { + struct type *enclosing_type = value_enclosing_type (val); + ULONGEST len = enclosing_type->length (); + if (check_size) - check_type_length_before_alloc (val->enclosing_type); - val->contents.reset - ((gdb_byte *) xzalloc (val->enclosing_type->length ())); + { + /* If we are allocating the contents of an array, which + is greater in size than max_value_size, and there is + an element limit in effect, then we can possibly try + to load only a sub-set of the array contents into + GDB's memory. */ + if (value_type (val) == enclosing_type + && value_type (val)->code () == TYPE_CODE_ARRAY + && len > max_value_size + && set_limited_array_length (val)) + len = val->limited_length; + else + check_type_length_before_alloc (enclosing_type); + } + + val->contents.reset ((gdb_byte *) xzalloc (len)); } } @@ -1789,10 +1900,7 @@ value_copy (const value *arg, bool check 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, check_size); + val = allocate_value_lazy (encl_type); val->type = arg->type; VALUE_LVAL (val) = arg->lval; val->location = arg->location; @@ -1808,17 +1916,41 @@ value_copy (const value *arg, bool check 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))) { gdb_assert (arg->contents != nullptr); - ULONGEST length = value_enclosing_type (arg)->length (); + allocate_value_contents (val, check_size); + + /* We need to handle the case where the new VAL has its content + buffer limited, but to a different length, than the original + ARG value. This all gets rather messy. */ + ULONGEST src_len, dst_len; + if (val->limited_length > 0) + dst_len = val->limited_length; + else + dst_len = value_enclosing_type (val)->length (); + + if (arg->limited_length > 0) + src_len = val->limited_length; + else + src_len = value_enclosing_type (arg)->length (); + + ULONGEST len = std::min (src_len, dst_len); + gdb::array_view val_contents + = value_contents_all_raw (val).slice (0, len); const auto &arg_view - = gdb::make_array_view (arg->contents.get (), length); - copy (arg_view, value_contents_all_raw (val)); + = gdb::make_array_view (arg->contents.get (), len); + copy (arg_view, val_contents); + + if (dst_len < src_len) + mark_value_bytes_unavailable (val, dst_len, (src_len - dst_len)); } - val->parent = arg->parent; if (VALUE_LVAL (val) == lval_computed) { const struct lval_funcs *funcs = val->location.computed.funcs; @@ -1961,20 +2093,40 @@ set_value_component_location (struct val int record_latest_value (struct value *val) { + struct type *enclosing_type = value_enclosing_type (val); + struct type *type = value_type (val); + /* We don't want this value to have anything to do with the inferior anymore. In particular, "set $1 = 50" should not affect the variable from which the value was taken, and fast watchpoints should be able to assume that a value on the value history never changes. */ if (value_lazy (val)) - value_fetch_lazy (val); + { + /* We know that this is a _huge_ array, any attempt to fetch this + is going to cause GDB to throw an error. However, to allow + the array to still be displayed we fetch its contents up to + `max_value_size' and mark anything beyond "unavailable" in + the history. */ + if (type->code () == TYPE_CODE_ARRAY + && type->length () > max_value_size + && array_length_limiting_element_count.has_value () + && enclosing_type == type + && calculate_limited_array_length (type) <= max_value_size) + val->limited_length = max_value_size; + + value_fetch_lazy (val); + } /* Don't pretend we have anything available there in the history beyond the boundaries of the value recorded. It's not like inferior memory where there is actual stuff underneath. */ - ULONGEST length = value_enclosing_type (val)->length (); + ULONGEST length = enclosing_type->length (); mark_value_bits_unavailable (val, LONGEST_MIN, 0 ^ LONGEST_MIN); mark_value_bits_unavailable (val, length * TARGET_CHAR_BIT, LONGEST_MAX - length * TARGET_CHAR_BIT); + if (val->limited_length != 0) + mark_value_bytes_unavailable (val, val->limited_length, + length - val->limited_length); /* We preserve VALUE_LVAL so that the user can find out where it was fetched from. This is a bit dubious, because then *&$1 does not just return $1 @@ -4071,10 +4223,23 @@ value_fetch_lazy_memory (struct value *v CORE_ADDR addr = value_address (val); struct type *type = check_typedef (value_enclosing_type (val)); - if (type->length ()) - read_value_memory (val, 0, value_stack (val), - addr, value_contents_all_raw (val).data (), - type_length_units (type)); + /* Figure out how much we should copy from memory. Usually, this is just + the size of the type, but, for arrays, we might only be loading a + small part of the array (this is only done for very large arrays). */ + int len = 0; + if (val->limited_length > 0) + { + gdb_assert (value_type (val)->code () == TYPE_CODE_ARRAY); + len = val->limited_length; + } + else if (type->length () > 0) + len = type_length_units (type); + + gdb_assert (len >= 0); + + if (len > 0) + read_value_memory (val, 0, value_stack (val), addr, + value_contents_all_raw (val).data (), len); } /* Helper for value_fetch_lazy when the value is in a register. */ Index: src/gdb/value.h =================================================================== --- src.orig/gdb/value.h +++ src/gdb/value.h @@ -1235,4 +1235,21 @@ extern void finalize_values (); of floating-point, fixed-point, or integer type. */ extern gdb_mpq value_to_gdb_mpq (struct value *value); +/* While an instance of this class is live, and array values that are + created, that are larger than max_value_size, will be restricted in size + to a particular number of elements. */ + +struct scoped_array_length_limiting +{ + /* Limit any large array values to only contain ELEMENTS elements. */ + scoped_array_length_limiting (int elements); + + /* Restore the previous array value limit. */ + ~scoped_array_length_limiting (); + +private: + /* Used to hold the previous array value element limit. */ + gdb::optional m_old_value; +}; + #endif /* !defined (VALUE_H) */