public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Offsets of FPR should be multiplied by 4 on 32-bit ppc
@ 2020-06-05  9:46 Huangsikai
  2020-06-11  0:38 ` Simon Marchi
  0 siblings, 1 reply; 2+ messages in thread
From: Huangsikai @ 2020-06-05  9:46 UTC (permalink / raw)
  To: gdb-patches
  Cc: liucheng32, chenzefeng2, wuquanming, zhuyan34, shaolexi,
	zengweilin, huangsikai

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


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Offsets of FPR should be multiplied by 4 on 32-bit ppc
  2020-06-05  9:46 [PATCH] Offsets of FPR should be multiplied by 4 on 32-bit ppc Huangsikai
@ 2020-06-11  0:38 ` Simon Marchi
  0 siblings, 0 replies; 2+ messages in thread
From: Simon Marchi @ 2020-06-11  0:38 UTC (permalink / raw)
  To: Huangsikai, gdb-patches
  Cc: zhuyan34, wuquanming, liucheng32, zengweilin, chenzefeng2, shaolexi

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

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-06-11  0:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-05  9:46 [PATCH] Offsets of FPR should be multiplied by 4 on 32-bit ppc Huangsikai
2020-06-11  0:38 ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).