+2020-12-24 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ PR gdb/27059
+ * eval.c (evaluate_subexp_for_sizeof): Handle not allocated and
+ not associated arrays.
+ * f-lang.c (fortran_adjust_dynamic_array_base_address_hack): Don't
+ adjust arrays that are not allocated/associated.
+ * gdbtypes.c (resolve_dynamic_range): Update header comment. Add
+ new parameter which is used to sometimes set dynamic properties to
+ undefined.
+ (resolve_dynamic_array_or_string): Update header comment. Add new
+ parameter which is used to guard evaluating dynamic properties.
+ Resolve allocated/associated properties first.
+
2020-12-24 Andrew Burgess <andrew.burgess@embecosm.com>
* gdbtypes (recursive_dump_type): Include allocated and associated
{
val = evaluate_subexp (nullptr, exp, pos, EVAL_NORMAL);
type = value_type (val);
- if (type->code () == TYPE_CODE_ARRAY
- && is_dynamic_type (type->index_type ())
- && type->bounds ()->high.kind () == PROP_UNDEFINED)
- return allocate_optimized_out_value (size_type);
+ if (type->code () == TYPE_CODE_ARRAY)
+ {
+ if (type_not_allocated (type) || type_not_associated (type))
+ return value_zero (size_type, not_lval);
+ else if (is_dynamic_type (type->index_type ())
+ && type->bounds ()->high.kind () == PROP_UNDEFINED)
+ return allocate_optimized_out_value (size_type);
+ }
}
else
(*pos) += 4;
{
gdb_assert (type->code () == TYPE_CODE_ARRAY);
+ /* We can't adjust the base address for arrays that have no content. */
+ if (type_not_allocated (type) || type_not_associated (type))
+ return address;
+
int ndimensions = calc_f77_array_dims (type);
LONGEST total_offset = 0;
/* Given a dynamic range type (dyn_range_type) and a stack of
struct property_addr_info elements, return a static version
- of that type. */
+ of that type.
+
+ When RESOLVE_P is true then the returned static range is created by
+ actually evaluating any dynamic properties within the range type, while
+ when RESOLVE_P is false the returned static range has all of the bounds
+ and stride information set to undefined. The RESOLVE_P set to false
+ case will be used when evaluating a dynamic array that is not
+ allocated, or not associated, i.e. the bounds information might not be
+ initialized yet. */
static struct type *
resolve_dynamic_range (struct type *dyn_range_type,
- struct property_addr_info *addr_stack)
+ struct property_addr_info *addr_stack,
+ bool resolve_p = true)
{
CORE_ADDR value;
struct type *static_range_type, *static_target_type;
gdb_assert (dyn_range_type->code () == TYPE_CODE_RANGE);
const struct dynamic_prop *prop = &dyn_range_type->bounds ()->low;
- if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
low_bound.set_const_val (value);
else
low_bound.set_undefined ();
prop = &dyn_range_type->bounds ()->high;
- if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
{
high_bound.set_const_val (value);
bool byte_stride_p = dyn_range_type->bounds ()->flag_is_byte_stride;
prop = &dyn_range_type->bounds ()->stride;
- if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
{
stride.set_const_val (value);
/* Resolves dynamic bound values of an array or string type TYPE to static
ones. ADDR_STACK is a stack of struct property_addr_info to be used if
- needed during the dynamic resolution. */
+ needed during the dynamic resolution.
+
+ When RESOLVE_P is true then the dynamic properties of TYPE are
+ evaluated, otherwise the dynamic properties of TYPE are not evaluated,
+ instead we assume the array is not allocated/associated yet. */
static struct type *
resolve_dynamic_array_or_string (struct type *type,
- struct property_addr_info *addr_stack)
+ struct property_addr_info *addr_stack,
+ bool resolve_p = true)
{
CORE_ADDR value;
struct type *elt_type;
type = copy_type (type);
- elt_type = type;
- range_type = check_typedef (elt_type->index_type ());
- range_type = resolve_dynamic_range (range_type, addr_stack);
-
- /* Resolve allocated/associated here before creating a new array type, which
- will update the length of the array accordingly. */
+ /* Resolve the allocated and associated properties before doing anything
+ else. If an array is not allocated or not associated then (at least
+ for Fortran) there is no guarantee that the data to define the upper
+ bound, lower bound, or stride will be correct. If RESOLVE_P is
+ already false at this point then this is not the first dimension of
+ the array and a more outer dimension has already marked this array as
+ not allocated/associated, as such we just ignore this property. This
+ is fine as GDB only checks the allocated/associated on the outer most
+ dimension of the array. */
prop = TYPE_ALLOCATED_PROP (type);
- if (prop != NULL && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
- prop->set_const_val (value);
+ if (prop != NULL && resolve_p
+ && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ {
+ prop->set_const_val (value);
+ if (value == 0)
+ resolve_p = false;
+ }
prop = TYPE_ASSOCIATED_PROP (type);
- if (prop != NULL && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
- prop->set_const_val (value);
+ if (prop != NULL && resolve_p
+ && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ {
+ prop->set_const_val (value);
+ if (value == 0)
+ resolve_p = false;
+ }
- ary_dim = check_typedef (TYPE_TARGET_TYPE (elt_type));
+ range_type = check_typedef (type->index_type ());
+ range_type = resolve_dynamic_range (range_type, addr_stack, resolve_p);
+ ary_dim = check_typedef (TYPE_TARGET_TYPE (type));
if (ary_dim != NULL && ary_dim->code () == TYPE_CODE_ARRAY)
- elt_type = resolve_dynamic_array_or_string (ary_dim, addr_stack);
+ elt_type = resolve_dynamic_array_or_string (ary_dim, addr_stack, resolve_p);
else
elt_type = TYPE_TARGET_TYPE (type);
prop = type->dyn_prop (DYN_PROP_BYTE_STRIDE);
- if (prop != NULL)
+ if (prop != NULL && resolve_p)
{
if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
{
+2020-12-24 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ PR gdb/27059
+ * gdb.dwarf2/dyn-type-unallocated.c: New file.
+ * gdb.dwarf2/dyn-type-unallocated.exp: New file.
+
2020-12-21 Peter Waller <p@pwaller.net>
* gdb.base/style-interp-exec-mi.exp: New.
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2020 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/>. */
+
+#include "../lib/attributes.h"
+
+/* Our fake dynamic object. */
+void *dyn_object;
+
+void __attribute__((noinline)) ATTRIBUTE_NOCLONE
+marker ()
+{ /* Nothing. */ }
+
+int
+main ()
+{
+ asm ("main_label: .globl main_label");
+
+ /* Initialise the dynamic object. */
+ dyn_object = 0;
+
+ asm ("marker_label: .globl marker_label");
+ marker (); /* Break here. */
+
+ return 0;
+}
+
--- /dev/null
+# Copyright 2020 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 for issue PR gdb/27059. The problem was that when resolving a
+# dynamic type that was not-allocated GDB would still try to execute
+# the DWARF expressions for the upper, lower, and byte-stride values.
+#
+# The problem is that, at least in some gfortran compiled programs,
+# these values are undefined until the array is allocated.
+#
+# As a result, executing the dwarf expressions was triggering integer
+# overflow in some cases.
+#
+# This test aims to make the sometimes occurring integer overflow a
+# more noticeable error by creating an array that is always marked as
+# not-allocated.
+#
+# The dwarf expressions for the various attributes then contains an
+# infinite loop. If GDB ever tries to execute these expressions we
+# will get a test timeout. With this issue fixed the expressions are
+# never executed and the test completes as we'd expect.
+
+load_lib dwarf.exp
+
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile .c -dw.S
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+ return -1
+}
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ cu {} {
+ global srcfile
+
+ compile_unit {
+ {producer "gcc" }
+ {language @DW_LANG_Fortran90}
+ {name ${srcfile}}
+ {low_pc 0 addr}
+ } {
+ declare_labels array_type_label integer_type_label
+
+ set int_size [get_sizeof "int" "UNKNOWN"]
+ set voidp_size [get_sizeof "void *" "UNKNOWN"]
+
+ integer_type_label: DW_TAG_base_type {
+ {DW_AT_byte_size $int_size DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name integer}
+ }
+
+ array_type_label: DW_TAG_array_type {
+ {DW_AT_type :$integer_type_label}
+ {DW_AT_data_location {
+ DW_OP_push_object_address
+ DW_OP_deref
+ } SPECIAL_expr}
+ {DW_AT_allocated {
+ DW_OP_lit0
+ } SPECIAL_expr}
+ } {
+ DW_TAG_subrange_type {
+ {DW_AT_type :$integer_type_label}
+ {DW_AT_lower_bound {
+ DW_OP_skip -3
+ } SPECIAL_expr}
+ {DW_AT_upper_bound {
+ DW_OP_skip -3
+ } SPECIAL_expr}
+ {DW_AT_byte_stride {
+ DW_OP_skip -3
+ } SPECIAL_expr}
+ }
+ }
+
+ DW_TAG_variable {
+ {DW_AT_location {
+ DW_OP_addr [gdb_target_symbol dyn_object]
+ } SPECIAL_expr}
+ {name "dyn_object"}
+ {type :$array_type_label}
+ }
+ subprogram {
+ {external 1 flag}
+ {MACRO_AT_func {main}}
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" "${testfile}" \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_breakpoint "marker_label"
+gdb_continue_to_breakpoint "stop at marker_label"
+gdb_test "ptype dyn_object" "type = integer, allocatable \\(:\\)"