summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2021-09-24 14:06:52 -0600
committerTom Tromey <tromey@adacore.com>2021-10-19 13:03:58 -0600
commit05fb05a94729473cb04b1299fe5c36e06525c78f (patch)
treeaedea01744e7289d9faef886a9ab2a2931edbdca
parentd7c68312bdeca52e242326e5cf155e0aa63268bb (diff)
downloadbinutils-gdb-05fb05a94729473cb04b1299fe5c36e06525c78f.tar.gz
Fix bug in dynamic type resolution
A customer-reported problem led us to a bug in dynamic type resolution. resolve_dynamic_struct will recursively call resolve_dynamic_type_internal, passing it the sub-object for the particular field being resolved. While it offsets the address here, it does not also offset the "valaddr" -- the array of bytes describing the memory. This patch fixes the bug, by offsetting both. A test case is included that can be used to reproduce the bug.
-rw-r--r--gdb/gdbtypes.c7
-rw-r--r--gdb/testsuite/gdb.ada/array_of_variant.exp11
-rw-r--r--gdb/testsuite/gdb.ada/array_of_variant/p.adb20
3 files changed, 35 insertions, 3 deletions
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index de73a2b5608..3110395b7cb 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2615,10 +2615,11 @@ resolve_dynamic_struct (struct type *type,
" (invalid location kind)"));
pinfo.type = check_typedef (resolved_type->field (i).type ());
+ size_t offset = TYPE_FIELD_BITPOS (resolved_type, i) / TARGET_CHAR_BIT;
pinfo.valaddr = addr_stack->valaddr;
- pinfo.addr
- = (addr_stack->addr
- + (TYPE_FIELD_BITPOS (resolved_type, i) / TARGET_CHAR_BIT));
+ if (!pinfo.valaddr.empty ())
+ pinfo.valaddr = pinfo.valaddr.slice (offset);
+ pinfo.addr = addr_stack->addr + offset;
pinfo.next = addr_stack;
resolved_type->field (i).set_type
diff --git a/gdb/testsuite/gdb.ada/array_of_variant.exp b/gdb/testsuite/gdb.ada/array_of_variant.exp
index 6372e2cf354..f8f4d9c130b 100644
--- a/gdb/testsuite/gdb.ada/array_of_variant.exp
+++ b/gdb/testsuite/gdb.ada/array_of_variant.exp
@@ -97,4 +97,15 @@ foreach_with_prefix scenario {all minimal} {
[string_to_regexp "$v2"] \
"python print second array element"
}
+
+ set av1 "(initial => 0, rest => (tag => unused, cval => 88 'X'))"
+ set av2 "(initial => 0, rest => (tag => object, ival => 88))"
+ set full "($av1, $av2)"
+
+ gdb_test "print another_array(1)" " = [string_to_regexp $av1]" \
+ "print first element of another_array"
+ gdb_test "print another_array(2)" " = [string_to_regexp $av2]" \
+ "print second element of another_array"
+ gdb_test "print another_array" " = [string_to_regexp $full]" \
+ "print another_array"
}
diff --git a/gdb/testsuite/gdb.ada/array_of_variant/p.adb b/gdb/testsuite/gdb.ada/array_of_variant/p.adb
index c475eb403f5..bf087af81b5 100644
--- a/gdb/testsuite/gdb.ada/array_of_variant/p.adb
+++ b/gdb/testsuite/gdb.ada/array_of_variant/p.adb
@@ -33,7 +33,27 @@ procedure P is
Objects : array (1 .. 2) of Payload_T;
+ type Another_Type (Tag : Tag_T := Unused) is
+ record
+ case Tag is
+ when Unused =>
+ CVal : Character;
+ when Object =>
+ IVal : Integer;
+ end case;
+ end record;
+
+ type Enclosing is record
+ Initial : Integer;
+ Rest : Another_Type;
+ end record;
+
+ Another_Array : array (1 .. 2) of Enclosing
+ := ((Initial => 0, Rest => (Tag => Unused, CVal => 'X')),
+ (Initial => 0, Rest => (Tag => Object, IVal => 88)));
+
begin
Objects (1) := (Tag => Object, Values => (others => 2));
Do_Nothing (Objects'Address); -- START
+ Do_Nothing (Another_Array'Address);
end P;