diff options
author | Tom de Vries <tdevries@suse.de> | 2025-01-15 17:02:00 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2025-01-15 17:02:00 +0100 |
commit | b034bb38772a0e1c16153ee7c68b4206421548d0 (patch) | |
tree | 836fa162b902adfb35e17cc4f1675b74f5c64aa7 /gdb/dwarf2 | |
parent | c4606bdbd580237478b6d6b4cdf4927134d31e5a (diff) | |
download | gdb-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.c | 31 |
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); |