aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2025-01-15 17:02:00 +0100
committerTom de Vries <tdevries@suse.de>2025-01-15 17:02:00 +0100
commitb034bb38772a0e1c16153ee7c68b4206421548d0 (patch)
tree836fa162b902adfb35e17cc4f1675b74f5c64aa7 /gdb/dwarf2
parentc4606bdbd580237478b6d6b4cdf4927134d31e5a (diff)
downloadgdb-b034bb38772a0e1c16153ee7c68b4206421548d0.zip
gdb-b034bb38772a0e1c16153ee7c68b4206421548d0.tar.gz
gdb-b034bb38772a0e1c16153ee7c68b4206421548d0.tar.bz2
[gdb] Add gdbarch_dwarf2_reg_piece_offset hook
In rw_pieced_value, when reading/writing part of a register, DW_OP_piece and DW_OP_bit_piece are handled the same, but the standard tells us: - DW_OP_piece: if the piece is located in a register, but does not occupy the entire register, the placement of the piece within that register is defined by the ABI. - DW_OP_bit_piece: if the location is a register, the offset is from the least significant bit end of the register. Add a new hook gdbarch_dwarf2_reg_piece_offset that allows us to define the ABI-specific behaviour for DW_OP_piece. The default implementation of the hook is the behaviour of DW_OP_bit_piece, so there should not be any functional changes. Tested on s390x-linux. Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb/dwarf2')
-rw-r--r--gdb/dwarf2/expr.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 2a1b851..ee1522b 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -211,14 +211,33 @@ rw_pieced_value (value *v, value *from, bool check_optimized)
ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum);
int optim, unavail;
- if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
- && p->offset + p->size < reg_bits)
+ if (p->offset + p->size < reg_bits)
{
- /* Big-endian, and we want less than full size. */
- bits_to_skip += reg_bits - (p->offset + p->size);
+ /* We want less than full size. */
+
+ if (p->op == DW_OP_piece)
+ {
+ gdb_assert (p->offset == 0);
+
+ /* If the piece is located in a register, but does not
+ occupy the entire register, the placement of the piece
+ within that register is defined by the ABI. */
+ bits_to_skip
+ += 8 * gdbarch_dwarf2_reg_piece_offset (arch, gdb_regnum,
+ p->size / 8);
+ }
+ else if (p->op == DW_OP_bit_piece)
+ {
+ /* If the location is a register, the offset is from the
+ least significant bit end of the register. */
+ if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
+ bits_to_skip += reg_bits - (p->offset + p->size);
+ else
+ bits_to_skip += p->offset;
+ }
+ else
+ error (_("Don't know how to get part of implicit pointer"));
}
- else
- bits_to_skip += p->offset;
this_size = bits_to_bytes (bits_to_skip, this_size_bits);
buffer.resize (this_size);