From b034bb38772a0e1c16153ee7c68b4206421548d0 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 15 Jan 2025 17:02:00 +0100 Subject: [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 --- gdb/findvar.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'gdb/findvar.c') diff --git a/gdb/findvar.c b/gdb/findvar.c index f7760aa..1a9d2be 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -541,6 +541,24 @@ default_value_from_register (gdbarch *gdbarch, type *type, int regnum, return value; } +/* Default implementation of gdbarch_dwarf2_reg_piece_offset. Implements + DW_OP_bits_piece for DW_OP_piece. */ + +ULONGEST +default_dwarf2_reg_piece_offset (gdbarch *gdbarch, int gdb_regnum, ULONGEST size) +{ + ULONGEST reg_size = register_size (gdbarch, gdb_regnum); + gdb_assert (size <= reg_size); + if (reg_size == size) + return 0; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + return reg_size - size; + + return 0; +} + + /* VALUE must be an lval_register value. If regnum is the value's associated register number, and len the length of the value's type, read one or more registers in VALUE's frame, starting with register REGNUM, -- cgit v1.1