[PATCH 2/9] Fix size capping in write_pieced_value

Andreas Arnez
2017-04-07T17:40:26Z

A field in a structure composed of DWARF pieces overlaps one or more of
those pieces. When writing to the field, the beginning of the first and
the end of the last of those pieces may have to be skipped. But the
logic in write_pieced_value for handling this is flawed when there are
actually bits to skip at the beginning of the first piece: it truncates
the piece size towards the end *before* accounting for the skipped bits
at the beginning instead of the other way around.

Note that the same bug was already found in read_pieced_value and fixed
there (but not in write_pieced_value), see PR 15391.

This patch swaps the calculations, bringing them into the same (correct)
order as in read_pieced_value.

gdb/ChangeLog:

* dwarf2loc.c (write_pieced_value): Fix order of calculations for
size capping.

gdb/testsuite/ChangeLog:

* gdb.dwarf2/var-pieces.exp: Add test case for modifying a
variable at nonzero offset.
---
gdb/dwarf2loc.c | 4 ++--
gdb/testsuite/gdb.dwarf2/var-access.exp | 5 +++++
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 93c45a7..496400a 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1963,8 +1963,6 @@ write_pieced_value (struct value *to, struct value *from)
bits_to_skip -= this_size_bits;
continue;
}
- if (this_size_bits > type_len - offset)
- this_size_bits = type_len - offset;
if (bits_to_skip > 0)
{
dest_offset_bits = bits_to_skip;
@@ -1977,6 +1975,8 @@ write_pieced_value (struct value *to, struct value *from)
dest_offset_bits = 0;
source_offset_bits = offset;
}
+ if (this_size_bits > type_len - offset)
+ this_size_bits = type_len - offset;

this_size = (this_size_bits + source_offset_bits % 8 + 7) / 8;
source_offset = source_offset_bits / 8;
diff --git a/gdb/testsuite/gdb.dwarf2/var-access.exp b/gdb/testsuite/gdb.dwarf2/var-access.exp
index ee93b93..56a635a 100644
--- a/gdb/testsuite/gdb.dwarf2/var-access.exp
+++ b/gdb/testsuite/gdb.dwarf2/var-access.exp
@@ -174,6 +174,11 @@ gdb_test "print/d s1" " = \\{a = 63, b = 3, c = 0, d = 1\\}" \
"verify s1.a"
gdb_test "print/d a" " = \\{0, 1, 63, 3, 4, 5, 6, 7\\}" \
"verify s1.a through a"
+gdb_test_no_output "set var s1.b = 42"
+gdb_test "print/d s1" " = \\{a = 63, b = 42, c = 0, d = 1\\}" \
+ "verify s1.b"
+gdb_test "print/d a" " = \\{0, 1, 63, 42, 4, 5, 6, 7\\}" \
+ "verify s1.b through a"

# Byte-aligned register- and memory pieces.
gdb_test_no_output "set var \$[lindex $regname 0] = 81" \
--
2.3.0