* [PATCH] Add PROP_VARIABLE
@ 2021-05-26 19:23 Tom Tromey
2021-05-29 3:36 ` Simon Marchi
0 siblings, 1 reply; 3+ messages in thread
From: Tom Tromey @ 2021-05-26 19:23 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
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 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 <tromey@adacore.com>
* dwarf2/read.h (dwarf2_fetch_die_type_sect_off): Add 'var_name'
parameter.
* dwarf2/loc.c (dwarf2_evaluate_property) <case PROP_VARIABLE>:
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) <PROP_VARIABLE>: New
constant.
(union dynamic_prop_data) <varname>: New member.
(struct dynamic_prop) <name, set_name>: New methods.
gdb/testsuite/ChangeLog
2020-09-30 Tom Tromey <tromey@adacore.com>
* 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 | 16 +++++
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, 311 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..22aa28eee15 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:
+ {
+ struct value *val = compute_var_value (prop->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 d3b5b89c1c3..6308366a5f7 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -18179,6 +18179,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. */
@@ -18233,7 +18252,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_name (name);
+ return 1;
+ }
+ return 0;
+ }
switch (target_attr->name)
{
@@ -23406,7 +23433,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;
@@ -23421,6 +23449,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 6af1f44bd47..25bd2f8a669 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -681,11 +681,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..ec258c12c11 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, /* 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 *varname;
};
/* * 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. */
+ const char *name () const
+ {
+ gdb_assert (m_kind == PROP_VARIABLE);
+ return m_data.varname;
+ }
+
+ /* Set the name of the variable that holds this property's value,
+ and set this property to be of kind PROP_VARIABLE. */
+ void set_name (const char *name)
+ {
+ m_kind = PROP_VARIABLE;
+ m_data.varname = 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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.
+
+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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Add PROP_VARIABLE
2021-05-26 19:23 [PATCH] Add PROP_VARIABLE Tom Tromey
@ 2021-05-29 3:36 ` Simon Marchi
2021-06-04 17:21 ` Tom Tromey
0 siblings, 1 reply; 3+ messages in thread
From: Simon Marchi @ 2021-05-29 3:36 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
> @@ -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. */
> + const char *name () const
> + {
> + gdb_assert (m_kind == PROP_VARIABLE);
> + return m_data.varname;
> + }
> +
> + /* Set the name of the variable that holds this property's value,
> + and set this property to be of kind PROP_VARIABLE. */
> + void set_name (const char *name)
> + {
> + m_kind = PROP_VARIABLE;
> + m_data.varname = name;
> + }
The logic of the getters / setters is that they match 1:1 the kinds
(although I see PROP_TYPE doesn't match original_type /
set_original_type, maybe a mistake). That makes it easier to follow:
you are only allowed to call the getter matching the prop's kind,
otherwise there's a logic error and you wouldn't get what you expect.
So I'd suggest maybe naming the enumerator PROP_VARIABLE_NAME, and then
have the variable_name / set_variable_name getter / setter.
Otherwise it LGTM.
Simon
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Add PROP_VARIABLE
2021-05-29 3:36 ` Simon Marchi
@ 2021-06-04 17:21 ` Tom Tromey
0 siblings, 0 replies; 3+ messages in thread
From: Tom Tromey @ 2021-06-04 17:21 UTC (permalink / raw)
To: Simon Marchi; +Cc: Tom Tromey, gdb-patches
>> + /* Set the name of the variable that holds this property's value,
>> + and set this property to be of kind PROP_VARIABLE. */
>> + void set_name (const char *name)
>> + {
>> + m_kind = PROP_VARIABLE;
>> + m_data.varname = name;
>> + }
Simon> The logic of the getters / setters is that they match 1:1 the kinds
Simon> (although I see PROP_TYPE doesn't match original_type /
Simon> set_original_type, maybe a mistake). That makes it easier to follow:
Simon> you are only allowed to call the getter matching the prop's kind,
Simon> otherwise there's a logic error and you wouldn't get what you expect.
Simon> So I'd suggest maybe naming the enumerator PROP_VARIABLE_NAME, and then
Simon> have the variable_name / set_variable_name getter / setter.
I made this change and will send an updated version soon.
Tom
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-06-04 17:21 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-26 19:23 [PATCH] Add PROP_VARIABLE Tom Tromey
2021-05-29 3:36 ` Simon Marchi
2021-06-04 17:21 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).