[PATCH] Offsets of FPR should be multiplied by 4 on 32-bit ppc
Simon Marchi
simark@simark.ca
Thu Jun 11 00:38:51 GMT 2020
On 2020-06-05 5:46 a.m., Huangsikai wrote:
> From: huangsikai <huangsikai@huawei.com>
>
> GDB:ppc32: calculate FPR address correctly on PPC32 with hard float
>
> GDB has trouble getting values from FPRs on PPC32 systems with hard float enabled.
>
> GDB first calculates the address of the register through the following code:
> if (tdep->ppc_fp0_regnum >= 0
> && regno >= tdep->ppc_fp0_regnum
> && regno < tdep->ppc_fp0_regnum + ppc_num_fprs)
> u_addr = (PT_FPR0 * wordsize) + ((regno - tdep->ppc_fp0_regnum) * 8);
>
> Then the address is passed into ptrace to fetch the value.
>
> And in kernel, ptrace gets the register index by the following code:
>
> #ifdef CONFIG_PPC32
> index = addr >> 2;
> if ((addr & 3) || (index > PT_FPSCR)
> || (child->thread.regs == NULL))
> #else
> index = addr >> 3;
> if ((addr & 7) || (index > PT_FPSCR))
> #endif
> break;
> ...
> unsigned int fpidx = index - PT_FPR0;
>
> It's easy to see the difference. GDB multiplies the register offset by 8,
> adds the starting address of FPR0 to get the address. But the kernel divides
> the address by 4, and then subtract the starting address of FPR0 to get the index.
> Consequently, suppose GDB tries to get the value from FPR1, the address passed
> into ptrace will mean FPR2.
>
> Therefore this constant should vary accordingly. As it's 4 in ppc32, 8 in ppc64,
> wordsize(which equals to sizeof(long)) will do the trick.
>
> Thanks,
> Allan
>
> Signed-off-by: huangsikai <huangsikai@huawei.com>
> ---
> gdb/ppc-linux-nat.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
> index 6be8f022a7..c78e554416 100644
> --- a/gdb/ppc-linux-nat.c
> +++ b/gdb/ppc-linux-nat.c
> @@ -659,7 +659,7 @@ ppc_register_u_addr (struct gdbarch *gdbarch, int regno)
> if (tdep->ppc_fp0_regnum >= 0
> && regno >= tdep->ppc_fp0_regnum
> && regno < tdep->ppc_fp0_regnum + ppc_num_fprs)
> - u_addr = (PT_FPR0 * wordsize) + ((regno - tdep->ppc_fp0_regnum) * 8);
> + u_addr = ((regno - tdep->ppc_fp0_regnum + PT_FPR0) * wordsize);
>
> /* UISA special purpose registers: 1 slot each. */
> if (regno == gdbarch_pc_regnum (gdbarch))
> --
> 2.12.3
>
By inspection, that makes sense to me. We would need to test for this. Is there a
test in the GDB testsuite that is currently failing that this patch fixes? If not,
please write or modify one to exercise that code.
You can check the testsuite/gdb.arch/ppc-* files, which are the ppc-specific tests.
There are already some floating point tests, so see if you can modify an existing
one, or add a new one.
Simon
More information about the Gdb-patches
mailing list