[PATCH] [gdb/tdep] Fix gdb.ada/O2_float_param.exp on s390x-linux
Tom de Vries
tdevries@suse.de
Fri Jan 24 15:44:18 GMT 2025
On 1/11/25 09:45, Tom de Vries wrote:
> With test-case gdb.ada/O2_float_param.exp on s390x-linux, I get:
> ...
> (gdb) frame^M
> #0 callee.increment (val=99.0, val@entry=<error reading variable: \
> register has not been saved in frame>, msg=...) at callee.adb:19^M
> 19 procedure Increment (Val : in out Float; Msg: String) is^M
> (gdb) FAIL: $exp: scenario=all: frame
> ...
>
> The frame command calls read_frame_arg to get:
> - the current value of val, and
> - the value of val at function entry.
>
> The first scenario succeeds, and the second scenario fails.
>
> For context and contrast, let's also investigate the first scenario: getting
> the current value of val.
>
> Function parameter val:
> ...
> <2><b51>: Abbrev Number: 4 (DW_TAG_formal_parameter)
> <b52> DW_AT_name : val
> <b58> DW_AT_type : <0xb86>
> <b5c> DW_AT_location : 0xab (location list)
> ...
> has location list:
> ...
> 000000ab 0000000001002928 0000000001002967
> (DW_OP_reg16 (f0))
> 000000be 0000000001002967 0000000001002968
> (DW_OP_reg24 (f8))
> 000000d1 0000000001002968 0000000001002974
> (DW_OP_GNU_regval_type: 24 (f8) <0xb29>;
> DW_OP_GNU_const_type: <0xb29> 4 byte block: 3f 80 0 0 ; DW_OP_plus;
> DW_OP_stack_value)
> 000000ef 0000000001002974 0000000001002982
> (DW_OP_GNU_entry_value: (DW_OP_GNU_regval_type: 16 (f0) <0xb29>);
> DW_OP_GNU_const_type: <0xb29> 4 byte block: 3f 80 0 0 ; DW_OP_plus;
> DW_OP_stack_value)
> 0000010f <End of list>
> ...
> and since we're stopped at address 0x1002928:
> ...
> (gdb) print $pc
> $1 = (access procedure) 0x1002928 <callee.increment>
> ...
> we get the value from dwarf register 16.
>
> The s390x ABI specifies that dwarf register 16 maps onto 8-byte register f0 or
> 16-byte register v0 (where f0 is part of v0), and in this case (because the
> v0 register is available) s390_dwarf_reg_to_regnum maps it to v0.
>
> Val is only 4 bytes:
> ...
> (gdb) ptype val
> type = <4-byte float>
> ...
> and s390_value_from_register takes care to get the value from the correct part
> of v0.
>
> The value of v0 is found in the prologue cache, and the value of parameter val
> is printed.
>
> Now the second scenario: getting the value of val at function entry.
>
> FWIW, since we're stopped at function entry, we could simply return the same
> value, reading the same register, but that's currently not implemented [2].
>
> Instead we start from the fact that val is in dwarf reg 16 at function entry,
> and then use call site information:
> ...
> <4><cf7>: Abbrev Number: 13 (DW_TAG_GNU_call_site)
> <cf8> DW_AT_low_pc : 0x1002a46
> <d00> DW_AT_abstract_origin: <0xdda>
> <5><d04>: Abbrev Number: 12 (DW_TAG_GNU_call_site_parameter)
> <d05> DW_AT_location : 1 byte block: 60 (DW_OP_reg16 (f0))
> <d07> DW_AT_GNU_call_site_value: 3 byte block: f5 18 2d \
> (DW_OP_GNU_regval_type: 24 (f8) <0xc42>)
> <5><d0b>: Abbrev Number: 12 (DW_TAG_GNU_call_site_parameter)
> ...
> to conclude that the value we're looking for is in dwarf reg 24, which
> s390_dwarf_reg_to_regnum maps to v8.
>
> As before, s390_value_from_register takes care to get the value from the
> correct part of v8.
>
> However, v8 is not available in the prologue cache, and we take a different
> path and end up in s390_unwind_pseudo_register, where v8 and similar
> (regnum_is_vxr_full) is unhandled, and we get:
> ...
> return value::allocate_optimized_out (type);
> ...
> which eventually causes the "error reading variable: register has not been
> saved in frame".
>
> Fix this by handling the regnum_is_vxr_full case in
> s390_unwind_pseudo_register, similar to how that is done in
> s390_pseudo_register_read.
>
I've pushed this.
Thanks,
- Tom
> Tested on s390x-linux.
>
> This also fixes test-case gdb.base/savedregs.exp.
>
> [1] https://github.com/IBM/s390x-abi
> [2] https://sourceware.org/pipermail/gdb-patches/2024-September/211589.html
> ---
> gdb/s390-tdep.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
> index 36a70d8642c..c57b6119e63 100644
> --- a/gdb/s390-tdep.c
> +++ b/gdb/s390-tdep.c
> @@ -2310,6 +2310,22 @@ s390_unwind_pseudo_register (const frame_info_ptr &this_frame, int regnum)
> return value_cast (type, val);
> }
>
> + if (regnum_is_vxr_full (tdep, regnum))
> + {
> + struct value *val = value::allocate_register (this_frame, regnum);
> +
> + int reg = regnum - tdep->v0_full_regnum;
> + struct value *val1
> + = frame_unwind_register_value (this_frame, S390_F0_REGNUM + reg);
> + struct value *val2
> + = frame_unwind_register_value (this_frame, S390_V0_LOWER_REGNUM + reg);
> +
> + val1->contents_copy (val, 0, 0, 8);
> + val2->contents_copy (val, 8, 0, 8);
> +
> + return value_cast (type, val);
> + }
> +
> return value::allocate_optimized_out (type);
> }
>
>
> base-commit: e564115c8a0e8f9b993cf0add01fa34548005d20
More information about the Gdb-patches
mailing list