Bug 21717 - "print $fpscr" says "<unavailable>" until some VFP data register is printed
Summary: "print $fpscr" says "<unavailable>" until some VFP data register is printed
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: tdep (show other bugs)
Version: 8.0
: P2 normal
Target Milestone: 8.0.1
Assignee: Yao Qi
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-07-05 20:58 UTC by Ruslan
Modified: 2017-07-25 09:26 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2017-07-21 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ruslan 2017-07-05 20:58:10 UTC
To reproduce:

1. Run the following command to start debuggee and stop at entry point:
gdb /bin/true -ex 'b *0' -ex r -ex 'd 1'

2. Issue "p $fpscr", see the output "$1 = <unavailable>" (the bug)
3. Issue "p $s0", see output "$2 = 0"
4. Now you can finally get FPSCR via "p $fpscr", having "$3 = 0" as output
5. Step one instruction using "si" command
6. Issue "p $fpscr" to see <unavailable> again

Tested on Raspberry Pi 1 Model B under Raspbian GNU/Linux 8.
/proc/cpuinfo says:
model name      : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS        : 697.95
Features        : half thumb fastmult vfp edsp java tls 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7

Hardware        : BCM2835
Revision        : 000e
Serial          : 000000009c40fec4
Comment 1 Yao Qi 2017-07-19 11:40:06 UTC
(In reply to Ruslan from comment #0)
> To reproduce:
> 
> 1. Run the following command to start debuggee and stop at entry point:
> gdb /bin/true -ex 'b *0' -ex r -ex 'd 1'

Could you show me the gdb output here?  I wonder why /bin/true 's entry is on address 0x0.
Comment 2 Ruslan 2017-07-19 13:50:10 UTC
(In reply to Yao Qi from comment #1)
> Could you show me the gdb output here?  I wonder why /bin/true 's entry is
> on address 0x0.

It's not on address zero. It's just a hack to make GDB stop on the first instruction available to the inferior process — otherwise, if you don't have debug symbols, you'll not be able to stop at the beginning of execution — be it _start or main (to my knowledge, this is the easiest way to achieve this).

Here's how the session begins:

$ gdb -q /bin/true -ex 'b *0' -ex r -ex 'd 1' -ex 'info reg $pc'
Reading symbols from /bin/true...(no debugging symbols found)...done.
Breakpoint 1 at 0x0
Starting program: /bin/true 
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x0

pc             0xb6fcfca0       0xb6fcfca0 <_start>
Comment 3 Yao Qi 2017-07-21 11:36:59 UTC
(In reply to Ruslan from comment #2)
> 
> Here's how the session begins:
> 
> $ gdb -q /bin/true -ex 'b *0' -ex r -ex 'd 1' -ex 'info reg $pc'
> Reading symbols from /bin/true...(no debugging symbols found)...done.
> Breakpoint 1 at 0x0
> Starting program: /bin/true 
> Warning:
> Cannot insert breakpoint 1.
> Cannot access memory at address 0x0
> 
> pc             0xb6fcfca0       0xb6fcfca0 <_start>

I still can't reproduce it on armv7l panda board,

gdb -q /bin/true -ex 'b *0' -ex r -ex 'd 1'

Reading symbols from /bin/true...(no debugging symbols found)...done.
Breakpoint 1 at 0x0
Starting program: /bin/true 

Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x0

(gdb) p $fpscr
$1 = 0

My board is armv7l, having vfp and vfpv3, but your board only has vfp.  I don't have armv6l hardware.

Can you build GDB from source and debug it yourself?  You can debug GDB by setting breakpoint on arm_linux_fetch_inferior_registers and fetch_vfp_regs,
and run GDB like this,

(gdb) run -q /bin/true -ex 'b *0' -ex r -ex 'd 1'

GDB should call arm_linux_fetch_inferior_registers first, and then it should call fetch_vfp_regs to fetch VFP registers.  I suspect "<unavailable>" is caused by that fetch_vfp_regs is not called.
Comment 4 Ruslan 2017-07-21 13:36:53 UTC
OK, here's what happens: in arm_linux_fetch_inferior_registers the last branch

      else if (tdep->vfp_register_count > 0
	       && regno >= ARM_D0_REGNUM
	       && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
	fetch_vfp_regs (regcache);

has tdep->vfp_register_count==16, while regno=90 (ARM_FPSCR_REGNUM). As ARM_D0_REGNUM==58, the call to fetch_vfp_regs(regcache) doesn't happen.

What seems to mismatch here is that VFP register count is 16, i.e. D0-D15, but enum gdb_regnum contains values up to ARM_D31_REGNUM, thus the next value, ARM_FPSCR_REGNUM, is not reached by the comparisons. Thus it's not surprising that the code does work on VFPv3, where there're 32 VFP double-precision registers.

I suppose there should be a "|| regno==ARM_FPSCR_REGNUM" or something like that inside the if-condition.
Comment 5 Yao Qi 2017-07-21 14:58:18 UTC
(In reply to Ruslan from comment #4)
> OK, here's what happens: in arm_linux_fetch_inferior_registers the last
> branch
> 
>       else if (tdep->vfp_register_count > 0
> 	       && regno >= ARM_D0_REGNUM
> 	       && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
> 	fetch_vfp_regs (regcache);
> 
> has tdep->vfp_register_count==16, while regno=90 (ARM_FPSCR_REGNUM). As
> ARM_D0_REGNUM==58, the call to fetch_vfp_regs(regcache) doesn't happen.
> 
> What seems to mismatch here is that VFP register count is 16, i.e. D0-D15,
> but enum gdb_regnum contains values up to ARM_D31_REGNUM, thus the next
> value, ARM_FPSCR_REGNUM, is not reached by the comparisons. Thus it's not
> surprising that the code does work on VFPv3, where there're 32 VFP
> double-precision registers.
> 
> I suppose there should be a "|| regno==ARM_FPSCR_REGNUM" or something like
> that inside the if-condition.

Indeed, I'll fix it.
Comment 6 Sourceware Commits 2017-07-25 09:07:31 UTC
The master branch has been updated by Yao Qi <qiyao@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=02ad7fc29f824a9742f8386bcf5793b81ff798f5

commit 02ad7fc29f824a9742f8386bcf5793b81ff798f5
Author: Yao Qi <yao.qi@linaro.org>
Date:   Fri Jul 21 16:35:23 2017 +0100

    [ARM] Access FPSCR on vfpv2
    
    GDB can fetch or store FPSCR on vfpv3, which has 32 VFP registers, but
    fail to do so on vfpv2, which has 16 VFP registers.  GDB code is incorrect
    for vfpv2,
    
           else if (tdep->vfp_register_count > 0
     	       && regno >= ARM_D0_REGNUM
    	       && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
    
    while FPSCR register number is defined as ARM_D0_REGNUM + 32.
    
      ARM_D0_REGNUM,		/* VFP double-precision registers.  */
      ARM_D31_REGNUM = ARM_D0_REGNUM + 31,
      ARM_FPSCR_REGNUM,
    
    The code above uses "<=" rather than "<", in order to put FPSCR in the
    range, but it is only correct when tdep->vfp_register_count is 32.  On
    vpfv2, it is 16, and FPSCR is out of the range, so fetch_vfp_regs or
    store_vfp_regs are not called.
    
    gdb:
    
    2017-07-25  Yao Qi  <yao.qi@linaro.org>
    
    	PR tdep/21717
    	* arm-linux-nat.c (arm_linux_fetch_inferior_registers): Update
    	condition for FPSCR.
    	(arm_linux_store_inferior_registers): Likewise.
Comment 7 Sourceware Commits 2017-07-25 09:16:50 UTC
The gdb-8.0-branch branch has been updated by Yao Qi <qiyao@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=50e64da58e648ff8708935add5b2a87b4e590edf

commit 50e64da58e648ff8708935add5b2a87b4e590edf
Author: Yao Qi <yao.qi@linaro.org>
Date:   Tue Jul 25 10:15:25 2017 +0100

    [ARM] Access FPSCR on vfpv2
    
    GDB can fetch or store FPSCR on vfpv3, which has 32 VFP registers, but
    fail to do so on vfpv2, which has 16 VFP registers.  GDB code is incorrect
    for vfpv2,
    
           else if (tdep->vfp_register_count > 0
     	       && regno >= ARM_D0_REGNUM
    	       && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
    
    while FPSCR register number is defined as ARM_D0_REGNUM + 32.
    
      ARM_D0_REGNUM,		/* VFP double-precision registers.  */
      ARM_D31_REGNUM = ARM_D0_REGNUM + 31,
      ARM_FPSCR_REGNUM,
    
    The code above uses "<=" rather than "<", in order to put FPSCR in the
    range, but it is only correct when tdep->vfp_register_count is 32.  On
    vpfv2, it is 16, and FPSCR is out of the range, so fetch_vfp_regs or
    store_vfp_regs are not called.
    
    gdb:
    
    2017-07-25  Yao Qi  <yao.qi@linaro.org>
    
    	PR tdep/21717
    	* arm-linux-nat.c (arm_linux_fetch_inferior_registers): Update
    	condition for FPSCR.
    	(arm_linux_store_inferior_registers): Likewise.
Comment 8 Yao Qi 2017-07-25 09:26:00 UTC
Patch is pushed to both master and 8.0 branch.  Close it.