From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from rock.gnat.com (rock.gnat.com [IPv6:2620:20:4000:0:a9e:1ff:fe9b:1d1]) by sourceware.org (Postfix) with ESMTPS id 3E31F385E036 for ; Fri, 4 Jun 2021 17:31:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3E31F385E036 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id EA26311787B; Fri, 4 Jun 2021 13:31:03 -0400 (EDT) X-Virus-Scanned: Debian amavisd-new at gnat.com Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id SVew4pOVAA1S; Fri, 4 Jun 2021 13:31:03 -0400 (EDT) Received: from murgatroyd.Home (75-166-132-3.hlrn.qwest.net [75.166.132.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPSA id A3A5A117876; Fri, 4 Jun 2021 13:31:03 -0400 (EDT) From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH v2] Add PROP_VARIABLE_NAME Date: Fri, 4 Jun 2021 11:30:59 -0600 Message-Id: <20210604173059.3021089-1-tromey@adacore.com> X-Mailer: git-send-email 2.26.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: , X-List-Received-Date: Fri, 04 Jun 2021 17:31:14 -0000 With -fgnat-encodings=minimal, an internal version (these patches will be upstreamed in the near future) of the Ada compiler can emit DWARF for an array where the bound comes from a variable, like: <1><12a7>: Abbrev Number: 7 (DW_TAG_array_type) <12a8> DW_AT_name : (indirect string, offset: 0x1ae9): pck__my_array [...] <2><12b4>: Abbrev Number: 8 (DW_TAG_subrange_type) <12b5> DW_AT_type : <0x1294> <12b9> DW_AT_upper_bound : <0x1277> With the upper bound DIE being: <1><1277>: Abbrev Number: 2 (DW_TAG_variable) <1278> DW_AT_name : (indirect string, offset: 0x1a4d): pck__my_length___U <127c> DW_AT_type : <0x128f> <1280> DW_AT_external : 1 <1280> DW_AT_artificial : 1 <1280> DW_AT_declaration : 1 Note that the variable is just a declaration -- in this situation, the variable comes from another compilation unit, and must be found when trying to compute the array bound. This patch adds a new PROP_VARIABLE_NAME kind, to enable this search. This same scenario can occur with DW_OP_GNU_variable_value, so this patch adds support for that as well. gdb/ChangeLog 2021-05-26 Tom Tromey * dwarf2/read.h (dwarf2_fetch_die_type_sect_off): Add 'var_name' parameter. * dwarf2/loc.c (dwarf2_evaluate_property) : New case. (compute_var_value): New function. (sect_variable_value): Use compute_var_value. * dwarf2/read.c (attr_to_dynamic_prop): Handle DW_TAG_variable. (var_decl_name): New function. (dwarf2_fetch_die_type_sect_off): Add 'var_name' parameter. * gdbtypes.h (enum dynamic_prop_kind) : New constant. (union dynamic_prop_data) : New member. (struct dynamic_prop) : New methods. gdb/testsuite/ChangeLog 2020-09-30 Tom Tromey * gdb.ada/array_of_symbolic_length.exp: New file. * gdb.ada/array_of_symbolic_length/foo.adb: New file. * gdb.ada/array_of_symbolic_length/gl.adb: New file. * gdb.ada/array_of_symbolic_length/gl.ads: New file. * gdb.ada/array_of_symbolic_length/pck.adb: New file. * gdb.ada/array_of_symbolic_length/pck.ads: New file. --- gdb/ChangeLog | 17 ++++++ gdb/dwarf2/loc.c | 37 +++++++++++- gdb/dwarf2/read.c | 34 ++++++++++- gdb/dwarf2/read.h | 7 ++- gdb/gdbtypes.h | 22 +++++++ gdb/testsuite/ChangeLog | 9 +++ .../gdb.ada/array_of_symbolic_length.exp | 59 +++++++++++++++++++ .../gdb.ada/array_of_symbolic_length/foo.adb | 25 ++++++++ .../gdb.ada/array_of_symbolic_length/gl.adb | 23 ++++++++ .../gdb.ada/array_of_symbolic_length/gl.ads | 18 ++++++ .../gdb.ada/array_of_symbolic_length/pck.adb | 23 ++++++++ .../gdb.ada/array_of_symbolic_length/pck.ads | 43 ++++++++++++++ 12 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 gdb/testsuite/gdb.ada/array_of_symbolic_length.exp create mode 100644 gdb/testsuite/gdb.ada/array_of_symbolic_length/foo.adb create mode 100644 gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.adb create mode 100644 gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.ads create mode 100644 gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.adb create mode 100644 gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.ads diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index e816f926696..b7e30e3cb4a 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -620,6 +620,19 @@ per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset, ctx->eval (block.data, block.size); } +/* A helper function to find the definition of NAME and compute its + value. Returns nullptr if the name is not found. */ + +static value * +compute_var_value (const char *name) +{ + struct block_symbol sym = lookup_symbol (name, nullptr, VAR_DOMAIN, + nullptr); + if (sym.symbol != nullptr) + return value_of_variable (sym.symbol, sym.block); + return nullptr; +} + /* Given context CTX, section offset SECT_OFF, and compilation unit data PER_CU, execute the "variable value" operation on the DIE found at SECT_OFF. */ @@ -629,8 +642,10 @@ sect_variable_value (struct dwarf_expr_context *ctx, sect_offset sect_off, dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile) { + const char *var_name = nullptr; struct type *die_type - = dwarf2_fetch_die_type_sect_off (sect_off, per_cu, per_objfile); + = dwarf2_fetch_die_type_sect_off (sect_off, per_cu, per_objfile, + &var_name); if (die_type == NULL) error (_("Bad DW_OP_GNU_variable_value DIE.")); @@ -638,9 +653,18 @@ sect_variable_value (struct dwarf_expr_context *ctx, sect_offset sect_off, /* Note: Things still work when the following test is removed. This test and error is here to conform to the proposed specification. */ if (die_type->code () != TYPE_CODE_INT + && die_type->code () != TYPE_CODE_ENUM + && die_type->code () != TYPE_CODE_RANGE && die_type->code () != TYPE_CODE_PTR) error (_("Type of DW_OP_GNU_variable_value DIE must be an integer or pointer.")); + if (var_name != nullptr) + { + value *result = compute_var_value (var_name); + if (result != nullptr) + return result; + } + struct type *type = lookup_pointer_type (die_type); struct frame_info *frame = get_selected_frame (_("No frame selected.")); return indirect_synthetic_pointer (sect_off, 0, per_cu, per_objfile, frame, @@ -2691,6 +2715,17 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop, *value = value_as_address (val); return true; } + + case PROP_VARIABLE_NAME: + { + struct value *val = compute_var_value (prop->variable_name ()); + if (val != nullptr) + { + *value = value_as_long (val); + return true; + } + } + break; } return false; diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 338003590dc..de79454a85f 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -18172,6 +18172,25 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) return set_die_type (die, type, cu); } +/* A helper function that returns the name of DIE, if it refers to a + variable declaration. */ + +static const char * +var_decl_name (struct die_info *die, struct dwarf2_cu *cu) +{ + if (die->tag != DW_TAG_variable) + return nullptr; + + attribute *attr = dwarf2_attr (die, DW_AT_declaration, cu); + if (attr == nullptr || !attr->as_boolean ()) + return nullptr; + + attr = dwarf2_attr (die, DW_AT_name, cu); + if (attr == nullptr) + return nullptr; + return attr->as_string (); +} + /* Parse dwarf attribute if it's a block, reference or constant and put the resulting value of the attribute into struct bound_prop. Returns 1 if ATTR could be resolved into PROP, 0 otherwise. */ @@ -18226,7 +18245,15 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, target_attr = dwarf2_attr (target_die, DW_AT_data_member_location, target_cu); if (target_attr == NULL) - return 0; + { + const char *name = var_decl_name (target_die, target_cu); + if (name != nullptr) + { + prop->set_variable_name (name); + return 1; + } + return 0; + } switch (target_attr->name) { @@ -23399,7 +23426,8 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off, struct type * dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu_data *per_cu, - dwarf2_per_objfile *per_objfile) + dwarf2_per_objfile *per_objfile, + const char **var_name) { struct die_info *die; @@ -23414,6 +23442,8 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, if (!die) return NULL; + if (var_name != nullptr) + *var_name = var_decl_name (die, cu); return die_type (die, cu); } diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index 6f45eea1268..ae1608fa822 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -671,11 +671,14 @@ extern const gdb_byte *dwarf2_fetch_constant_bytes LONGEST *len); /* Return the type of the die at SECT_OFF in PER_CU. Return NULL if no - valid type for this die is found. */ + valid type for this die is found. If VAR_NAME is non-null, and if + the DIE in question is a variable declaration (definitions are + excluded), then *VAR_NAME is set to the variable's name. */ struct type *dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu_data *per_cu, - dwarf2_per_objfile *per_objfile); + dwarf2_per_objfile *per_objfile, + const char **var_name = nullptr); /* When non-zero, dump line number entries as they are read in. */ extern unsigned int dwarf_line_debug; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index bb4d26eef1a..0cc00e74a20 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -388,6 +388,7 @@ enum dynamic_prop_kind PROP_LOCLIST, /* Location list. */ PROP_VARIANT_PARTS, /* Variant parts. */ PROP_TYPE, /* Type. */ + PROP_VARIABLE_NAME, /* Variable name. */ }; union dynamic_prop_data @@ -414,6 +415,11 @@ union dynamic_prop_data rewrite the property's kind and set this field. */ struct type *original_type; + + /* Name of a variable to look up; the variable holds the value of + this property. */ + + const char *variable_name; }; /* * Used to store a dynamic property. */ @@ -496,6 +502,22 @@ struct dynamic_prop m_data.original_type = original_type; } + /* Return the name of the variable that holds this property's value. + Only valid for PROP_VARIABLE_NAME. */ + const char *variable_name () const + { + gdb_assert (m_kind == PROP_VARIABLE_NAME); + return m_data.variable_name; + } + + /* Set the name of the variable that holds this property's value, + and set this property to be of kind PROP_VARIABLE_NAME. */ + void set_variable_name (const char *name) + { + m_kind = PROP_VARIABLE_NAME; + m_data.variable_name = name; + } + /* Determine which field of the union dynamic_prop.data is used. */ enum dynamic_prop_kind m_kind; diff --git a/gdb/testsuite/gdb.ada/array_of_symbolic_length.exp b/gdb/testsuite/gdb.ada/array_of_symbolic_length.exp new file mode 100644 index 00000000000..aa53445512d --- /dev/null +++ b/gdb/testsuite/gdb.ada/array_of_symbolic_length.exp @@ -0,0 +1,59 @@ +# 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 . + +load_lib "ada.exp" + +if { [skip_ada_tests] } { return -1 } + +standard_ada_testfile foo + +foreach_with_prefix scenario {all minimal} { + set flags [list debug additional_flags=-fgnat-encodings=$scenario] + + if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != ""} { + return -1 + } + + clean_restart ${testfile} + + set bp_location [gdb_get_line_number "BREAK" ${testdir}/foo.adb] + runto "foo.adb:$bp_location" + + set test "print my_value" + gdb_test_multiple "$test" $test { + -re " = \\(23, 23, 23, 23, 23, 23, 23\\).*$gdb_prompt $" { + pass $test + } + -re " = \\(\\).*$gdb_prompt $" { + if {$scenario == "minimal"} { + setup_kfail "minimal encodings" *-*-* + } + fail $test + } + } + + set test "print rt" + gdb_test_multiple "$test" $test { + -re " = \\(a => \\(\\(a1 => \\(4, 4\\), a2 => \\(8, 8\\)\\), \\(a1 => \\(4, 4\\), a2 => \\(8, 8\\)\\)\\)\\).*$gdb_prompt $" { + pass $test + } + -re " = \\(a => \\(\\)\\).*$gdb_prompt $" { + if {$scenario == "minimal"} { + setup_kfail "minimal encodings" *-*-* + } + fail $test + } + } +} diff --git a/gdb/testsuite/gdb.ada/array_of_symbolic_length/foo.adb b/gdb/testsuite/gdb.ada/array_of_symbolic_length/foo.adb new file mode 100644 index 00000000000..dc982ba42b9 --- /dev/null +++ b/gdb/testsuite/gdb.ada/array_of_symbolic_length/foo.adb @@ -0,0 +1,25 @@ +-- 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 . + +with Pck; use Pck; +with System; + +procedure Foo is + My_Value : My_Array := (others => 23); + Rt : Outer := (A => (others => (A1 => (others => 4), + A2 => (others => 8)))); +begin + Do_Nothing (My_Value'Address); -- BREAK +end Foo; diff --git a/gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.adb b/gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.adb new file mode 100644 index 00000000000..aef7391d319 --- /dev/null +++ b/gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.adb @@ -0,0 +1,23 @@ +-- 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 . + +package body Gl is + + function Length return Natural is + begin + return 7; + end Length; + +end Gl; diff --git a/gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.ads b/gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.ads new file mode 100644 index 00000000000..1257c2e2017 --- /dev/null +++ b/gdb/testsuite/gdb.ada/array_of_symbolic_length/gl.ads @@ -0,0 +1,18 @@ +-- 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 . + +package Gl is + function Length return Natural; +end Gl; diff --git a/gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.adb b/gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.adb new file mode 100644 index 00000000000..001bac46a18 --- /dev/null +++ b/gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.adb @@ -0,0 +1,23 @@ +-- 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 . + +package body Pck is + + procedure Do_Nothing (A : System.Address) is + begin + null; + end Do_Nothing; + +end Pck; diff --git a/gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.ads b/gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.ads new file mode 100644 index 00000000000..938d2a23738 --- /dev/null +++ b/gdb/testsuite/gdb.ada/array_of_symbolic_length/pck.ads @@ -0,0 +1,43 @@ +-- 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 . + +with System; +with Gl; use Gl; + +package Pck is + + subtype My_Length is Natural range 1 .. Length; + type My_Array is array (My_Length) of Natural; + + N_A : Integer := 2; + N_T : Integer := 2; + + type Arr is array (Positive range <>) of Integer; + + type Inner is + record + A1 : Arr (1 .. N_A); + A2 : Arr (1 .. N_A); + end record; + type Inner_Arr is array (Positive range <>) of Inner; + + type Outer is + record + A : Inner_Arr (1 .. N_T); + end record; + + procedure Do_Nothing (A : System.Address); + +end Pck; -- 2.26.3