From: Andreas Arnez <arnez@linux.vnet.ibm.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 5/9] Fix issues in write_pieced_value when targeting bit-fields
Date: Fri, 07 Apr 2017 17:42:00 -0000 [thread overview]
Message-ID: <1491586736-21296-6-git-send-email-arnez@linux.vnet.ibm.com> (raw)
In-Reply-To: <1491586736-21296-1-git-send-email-arnez@linux.vnet.ibm.com>
There are multiple issues in write_pieced_value when dealing with a
bit-field as the target value:
(1) The number of bits preceding the bit-field is calculated without
considering the relative offset of the value's parent.
(2) On big-endian targets the source value's *most* significant bits are
transferred to the target value, instead of its least significant
bits.
(3) The number of bytes containing a portion of the bit-field in a given
piece is calculated with the wrong starting offset; thus the result
may be off by one.
(4) When checking whether the data can be transferred byte-wise, the
transfer size is not verified to be byte-aligned.
(5) When transferring the data via a buffer, the bit offset within the
target value is not reduced to its sub-byte fraction before using it
as a bit offset into the buffer.
These issues are fixed. For consistency, the affected logic that exists
in read_pieced_value as well is changed there in the same way.
gdb/ChangeLog:
* dwarf2loc.c (write_pieced_value): Fix various issues with
bit-field handling.
(read_pieced_value): Sync with changes in write_pieced_value.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/var-access.exp: Add test for accessing bit-fields
whose containing structure is located in several DWARF pieces.
---
gdb/dwarf2loc.c | 54 +++++++++++++++------------------
gdb/testsuite/gdb.dwarf2/var-access.exp | 50 +++++++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 30 deletions(-)
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 76a58a3..1f89a08 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1775,7 +1775,8 @@ read_pieced_value (struct value *v)
bits_to_skip = 8 * value_offset (v);
if (value_bitsize (v))
{
- bits_to_skip += value_bitpos (v);
+ bits_to_skip += (8 * value_offset (value_parent (v))
+ + value_bitpos (v));
type_len = value_bitsize (v);
}
else
@@ -1796,18 +1797,11 @@ read_pieced_value (struct value *v)
bits_to_skip -= this_size_bits;
continue;
}
- if (bits_to_skip > 0)
- {
- dest_offset_bits = 0;
- source_offset_bits = bits_to_skip;
- this_size_bits -= bits_to_skip;
- bits_to_skip = 0;
- }
- else
- {
- dest_offset_bits = offset;
- source_offset_bits = 0;
- }
+ source_offset_bits = bits_to_skip;
+ this_size_bits -= bits_to_skip;
+ bits_to_skip = 0;
+ dest_offset_bits = offset;
+
if (this_size_bits > type_len - offset)
this_size_bits = type_len - offset;
@@ -1942,8 +1936,16 @@ write_pieced_value (struct value *to, struct value *from)
bits_to_skip = 8 * value_offset (to);
if (value_bitsize (to))
{
- bits_to_skip += value_bitpos (to);
+ bits_to_skip += (8 * value_offset (value_parent (to))
+ + value_bitpos (to));
type_len = value_bitsize (to);
+ /* Use the least significant bits of FROM. */
+ if (gdbarch_byte_order (get_type_arch (value_type (from)))
+ == BFD_ENDIAN_BIG)
+ {
+ offset = 8 * TYPE_LENGTH (value_type (from)) - type_len;
+ type_len += offset;
+ }
}
else
type_len = 8 * TYPE_LENGTH (value_type (to));
@@ -1962,25 +1964,19 @@ write_pieced_value (struct value *to, struct value *from)
bits_to_skip -= this_size_bits;
continue;
}
- if (bits_to_skip > 0)
- {
- dest_offset_bits = bits_to_skip;
- source_offset_bits = 0;
- this_size_bits -= bits_to_skip;
- bits_to_skip = 0;
- }
- else
- {
- dest_offset_bits = 0;
- source_offset_bits = offset;
- }
+ dest_offset_bits = bits_to_skip;
+ this_size_bits -= bits_to_skip;
+ bits_to_skip = 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;
+ this_size = (this_size_bits + dest_offset_bits % 8 + 7) / 8;
source_offset = source_offset_bits / 8;
dest_offset = dest_offset_bits / 8;
- if (dest_offset_bits % 8 == 0 && source_offset_bits % 8 == 0)
+ if (dest_offset_bits % 8 == 0 && source_offset_bits % 8 == 0
+ && this_size_bits % 8 == 0)
{
source_buffer = contents + source_offset;
need_bitwise = 0;
@@ -2049,7 +2045,7 @@ write_pieced_value (struct value *to, struct value *from)
read_memory (p->v.mem.addr + dest_offset, buffer.data (), 1);
read_memory (p->v.mem.addr + dest_offset + this_size - 1,
&buffer[this_size - 1], 1);
- copy_bitwise (buffer.data (), dest_offset_bits,
+ copy_bitwise (buffer.data (), dest_offset_bits % 8,
contents, source_offset_bits,
this_size_bits,
bits_big_endian);
diff --git a/gdb/testsuite/gdb.dwarf2/var-access.exp b/gdb/testsuite/gdb.dwarf2/var-access.exp
index 56a635a..c6abc87 100644
--- a/gdb/testsuite/gdb.dwarf2/var-access.exp
+++ b/gdb/testsuite/gdb.dwarf2/var-access.exp
@@ -62,7 +62,7 @@ Dwarf::assemble $asm_file {
} {
declare_labels char_type_label
declare_labels int_type_label short_type_label
- declare_labels array_a8_label struct_s_label
+ declare_labels array_a8_label struct_s_label struct_t_label
char_type_label: base_type {
{name "char"}
@@ -111,6 +111,34 @@ Dwarf::assemble $asm_file {
}
}
+ struct_t_label: structure_type {
+ {name "t"}
+ {byte_size 8 DW_FORM_sdata}
+ } {
+ member {
+ {name u}
+ {type :$int_type_label}
+ }
+ member {
+ {name x}
+ {type :$int_type_label}
+ {data_member_location 4 DW_FORM_udata}
+ {bit_size 9 DW_FORM_udata}
+ }
+ member {
+ {name y}
+ {type :$int_type_label}
+ {data_bit_offset 41 DW_FORM_udata}
+ {bit_size 13 DW_FORM_udata}
+ }
+ member {
+ {name z}
+ {type :$int_type_label}
+ {data_bit_offset 54 DW_FORM_udata}
+ {bit_size 10 DW_FORM_udata}
+ }
+ }
+
DW_TAG_subprogram {
{name "main"}
{DW_AT_external 1 flag}
@@ -152,6 +180,18 @@ Dwarf::assemble $asm_file {
piece 1
} SPECIAL_expr}
}
+ # Memory pieces for bitfield access.
+ DW_TAG_variable {
+ {name "t1"}
+ {type :$struct_t_label}
+ {location {
+ piece 4
+ addr "$buf_var + 1"
+ piece 3
+ addr "$buf_var"
+ piece 1
+ } SPECIAL_expr}
+ }
}
}
}
@@ -196,3 +236,11 @@ gdb_test_no_output "set var s2 = {191, 73, 231, 123}" \
"re-initialize s2"
gdb_test "print/d s2" " = \\{a = 191, b = 73, c = 231, d = 123\\}" \
"verify re-initialized s2"
+
+# Unaligned bitfield access through byte-aligned pieces.
+gdb_test_no_output "set var t1.x = -7"
+gdb_test_no_output "set var t1.z = 340"
+gdb_test_no_output "set var t1.y = 1234"
+gdb_test "print t1" " = \\{u = <optimized out>, x = -7, y = 1234, z = 340\\}" \
+ "verify t1"
+
--
2.3.0
next prev parent reply other threads:[~2017-04-07 17:42 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-07 17:39 [PATCH 0/9] Various DWARF piece fixes Andreas Arnez
2017-04-07 17:39 ` [PATCH 1/9] Add test for modifiable DWARF locations Andreas Arnez
2017-04-13 4:00 ` Simon Marchi
2017-04-13 10:52 ` Andreas Arnez
2017-04-13 8:36 ` Yao Qi
2017-04-13 11:46 ` Andreas Arnez
2017-04-07 17:40 ` [PATCH 2/9] Fix size capping in write_pieced_value Andreas Arnez
2017-04-13 8:18 ` Yao Qi
2017-04-13 16:35 ` Andreas Arnez
2017-04-19 9:15 ` Yao Qi
2017-04-19 14:36 ` Andreas Arnez
2017-04-19 15:00 ` Yao Qi
2017-04-07 17:41 ` [PATCH 4/9] Remove addr_size field from struct piece_closure Andreas Arnez
2017-04-13 9:10 ` Yao Qi
2017-04-14 3:39 ` Simon Marchi
2017-04-18 17:25 ` Andreas Arnez
2017-04-18 18:49 ` Simon Marchi
2017-04-07 17:41 ` [PATCH 3/9] PR gdb/21226: Take DWARF stack value pieces from LSB end Andreas Arnez
2017-04-14 3:36 ` Simon Marchi
2017-04-18 16:32 ` Andreas Arnez
2017-04-18 16:43 ` Simon Marchi
2017-04-07 17:42 ` Andreas Arnez [this message]
2017-04-14 5:18 ` [PATCH 5/9] Fix issues in write_pieced_value when targeting bit-fields Simon Marchi
2017-04-27 17:54 ` Andreas Arnez
2017-05-03 13:59 ` Simon Marchi
2017-04-07 17:43 ` [PATCH 7/9] Improve logic for buffer allocation in read/write_pieced_value Andreas Arnez
2017-04-14 14:51 ` Simon Marchi
2017-04-07 17:43 ` [PATCH 6/9] Fix handling of DWARF register pieces on big-endian targets Andreas Arnez
2017-04-14 14:11 ` Simon Marchi
2017-04-19 18:03 ` Andreas Arnez
2017-04-07 17:44 ` [PATCH 8/9] Respect piece offset for DW_OP_bit_piece Andreas Arnez
2017-04-14 15:07 ` Simon Marchi
2017-04-07 17:45 ` [PATCH 9/9] Remove unnecessary copies of variables in read/write_pieced_value Andreas Arnez
2017-04-14 15:21 ` Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1491586736-21296-6-git-send-email-arnez@linux.vnet.ibm.com \
--to=arnez@linux.vnet.ibm.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox