riscv: missing FPU register declaration makes gdb flatly reject the file
mean00 opened this issue · comments
Hi,
With a RV32 binary generated using hw fp ( such as available on the ch32v3xxx), the resulting binary is flatly rejected by blackmagic + gdb (tried several versions including gdb 13.2)
It seems the underlying reason is that gdb is trying to find the relevant registers in the xml description, does not find them, and then let the descriptor incomplete and full of null pointers.
As a result it sort of asserts with a message along "bfd requires flen 4, but target has flen 0"
I have an incomplete patch, which declares the relevant registers (in single precision) if the single fp extension is there, so that gdb is happy and loads the file.
It is incomplete, accessing the FPU registers ends up with warnings/errors (no crash though)
I dont know if submitting that incomplete patch is better than nothing or if you prefer to wait till someone (may take some times in my case ) provides a fully operational patch.
Thank you
The RISC-V FPU handling in BMD is purely a stub, and we had absolute heck trying to figure out what GDB considers the RISC-V FPU to look like for a register description and how any of that would work and look as none of our test parts have one. Any information you can share that gets that improved or fixed is welcome!
To be more specific,
blackmagic/src/target/riscv_debug.c
Line 1002 in c4015cd
blackmagic/src/target/cortexar.c
Lines 1682 to 1704 in c4015cd
blackmagic/src/target/cortexar.c
Lines 1765 to 1771 in c4015cd
My approach was to look in actual gdb code (13.2) and the initial report from sifive
( https://patchwork.kernel.org/project/qemu-devel/patch/20181228220731.4753-1-jimw@sifive.com/ )
The relevant part are these (full patch attached for reference)
static const char *riscv_fpu_regs[] ={"t0","t1","t2", "t3","t4","t5","t6","t7",
"s0","s1","a0","a1","a2","a3","a4",
"a5","a6","a7","s2","s3","s4","s5",
"s6","s7","s8","s9","s10","s11","t8",
"t9","t10","t11"};static const char *riscv_fpu_ctrl_regs[]={"flags","rm","csr"};
/* Basic single precision support */ if (extensions & RV_ISA_EXT_SINGLE_FLOAT) { const int first_fpu_register = 33; // fixme! const int first_fpu_control_register = 66; // fixme! if (max_length != 0) print_size = max_length - (size_t)offset; offset += snprintf(buffer + offset, print_size, "</feature><feature name=\"org.gnu.gdb.riscv.fpu\">"); for (int i = 0; i < sizeof(riscv_fpu_regs) / sizeof(riscv_fpu_regs[0]); i++) { if (max_length != 0) print_size = max_length - (size_t)offset; offset += snprintf(buffer + offset, print_size, "<reg name=\"f%s\" bitsize=\"32\" type=\"ieee_single\" regnum=\"%u\" group=\"float\"/>", riscv_fpu_regs[i], i + first_fpu_register); } for (int i = 0; i < sizeof(riscv_fpu_ctrl_regs) / sizeof(riscv_fpu_ctrl_regs[0]); i++) { if (max_length != 0) print_size = max_length - (size_t)offset; offset += snprintf(buffer + offset, print_size, "<reg name=\"f%s\" bitsize=\"32\" type=\"int\" regnum=\"%u\" group=\"float\" save-restore=\"no\"/>", riscv_fpu_ctrl_regs[i], i + first_fpu_control_register); } }
with that, gdb accepts the binary and i can debug it. Of course everything related to the fpu registers is not working.
I've seen that the csrs related to the fpu (fflags etc.. ) MAY be duplicated also in the csr sections, it's not crystal clear.
Thank you.
(and it is 32 bits only)