diff options
-rw-r--r-- | gdb/testsuite/gdb.base/non-lazy-array-index.c | 31 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/non-lazy-array-index.exp | 78 | ||||
-rw-r--r-- | gdb/valarith.c | 18 |
3 files changed, 118 insertions, 9 deletions
diff --git a/gdb/testsuite/gdb.base/non-lazy-array-index.c b/gdb/testsuite/gdb.base/non-lazy-array-index.c new file mode 100644 index 0000000..4140b67 --- /dev/null +++ b/gdb/testsuite/gdb.base/non-lazy-array-index.c @@ -0,0 +1,31 @@ +/* Copyright 2021 Free Software Foundation, Inc. + + This file is part of GDB. + + 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/>. */ + +struct foo_t +{ + float f; + + int array[5]; +}; + +struct foo_t global_foo = { 1.0f, { 1, 2, 3, 4, 5 } }; + +int +main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/non-lazy-array-index.exp b/gdb/testsuite/gdb.base/non-lazy-array-index.exp new file mode 100644 index 0000000..c837f9a --- /dev/null +++ b/gdb/testsuite/gdb.base/non-lazy-array-index.exp @@ -0,0 +1,78 @@ +# Copyright 2021 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/>. + +# Check that GDB does not do excess accesses to the inferior memory +# when fetching elements from an array in the C language. + +standard_testfile + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} { + return -1 +} + +if ![runto_main] then { + return -1 +} + +# Load 'global_foo' into a history variable. +gdb_test "p global_foo" "\\{f = 1, array = \\{1, 2, 3, 4, 5\\}\\}" + +gdb_test_no_output "set debug target 1" + +# Now print an array element from within 'global_foo', but accessed +# via the history element. The history element should be non-lazy, +# and so there should be no reason for GDB to fetch the array element +# from the inferior memory, we should be able to grab the contents +# directory from the history value. +# +# To check this we 'set debug target 1' (above), and then look for any +# xfer_partial calls; there shouldn't be any. +set saw_memory_access false +gdb_test_multiple "p \$.array\[1\]" "" { + -re "^p \\\$\\.array\\\[1\\\]\r\n" { + exp_continue + } + -re "^->\[^\r\n\]+xfer_partial\[^\r\n\]+\r\n" { + set saw_memory_access true + exp_continue + } + -re "^->\[^\r\n\]+\r\n" { + exp_continue + } + -re "^<-\[^\r\n\]+\r\n" { + exp_continue + } + -re "^\[^\$\]\[^\r\n\]+\r\n" { + exp_continue + } + -re "^\\\$${decimal} = 2\r\n$gdb_prompt " { + gdb_assert { ! $saw_memory_access } + } +} + +gdb_test "set debug target 0" ".*" + +if { ! [skip_python_tests] } { + gdb_test_no_output "python val = gdb.parse_and_eval('global_foo')" + gdb_test "python print('val = %s' % val)" "val = \\{f = 1, array = \\{1, 2, 3, 4, 5\\}\\}" + gdb_test "python print('val.is_lazy = %s' % val.is_lazy)" "val\\.is_lazy = False" + + # Grab an element from the array within VAL. The element should + # immediately be non-lazy as the value contents can be copied + # directly from VAL. + gdb_test_no_output "python elem = val\['array'\]\[1\]" + gdb_test "python print('elem.is_lazy = %s' % elem.is_lazy)" "elem\\.is_lazy = False" + gdb_test "python print('elem = %s' % elem)" "elem = 2" +} diff --git a/gdb/valarith.c b/gdb/valarith.c index 5ce9313..a0d0c60 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -162,17 +162,17 @@ value_subscript (struct value *array, LONGEST index) if (VALUE_LVAL (array) != lval_memory) return value_subscripted_rvalue (array, index, *lowerbound); - if (!c_style) - { - gdb::optional<LONGEST> upperbound - = get_discrete_high_bound (range_type); + gdb::optional<LONGEST> upperbound + = get_discrete_high_bound (range_type); - if (!upperbound.has_value ()) - upperbound = 0; + if (!upperbound.has_value ()) + upperbound = -1; - if (index >= *lowerbound && index <= *upperbound) - return value_subscripted_rvalue (array, index, *lowerbound); + if (index >= *lowerbound && index <= *upperbound) + return value_subscripted_rvalue (array, index, *lowerbound); + if (!c_style) + { /* Emit warning unless we have an array of unknown size. An array of unknown size has lowerbound 0 and upperbound -1. */ if (*upperbound > -1) @@ -200,7 +200,7 @@ value_subscripted_rvalue (struct value *array, LONGEST index, LONGEST lowerbound) { struct type *array_type = check_typedef (value_type (array)); - struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type)); + struct type *elt_type = TYPE_TARGET_TYPE (array_type); LONGEST elt_size = type_length_units (elt_type); /* Fetch the bit stride and convert it to a byte stride, assuming 8 bits |