X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Friscv-linux-nat.c;h=4f78dfdc6a20f447863b1821a598c0434afaa5e7;hb=8118159c69a957292ce701b3d2937f19a0d0f973;hp=7a96b7b0743ae479631d70c79ae2cbcdb17b388c;hpb=6c2659886f7018fcca26ee0fc813bc9748fb8513;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/riscv-linux-nat.c b/gdb/riscv-linux-nat.c index 7a96b7b074..4f78dfdc6a 100644 --- a/gdb/riscv-linux-nat.c +++ b/gdb/riscv-linux-nat.c @@ -22,12 +22,18 @@ #include "linux-nat.h" #include "riscv-tdep.h" #include "inferior.h" -#include "target-descriptions.h" #include "elf/common.h" +#include "nat/riscv-linux-tdesc.h" + #include +/* Work around glibc header breakage causing ELF_NFPREG not to be usable. */ +#ifndef NFPREG +# define NFPREG 33 +#endif + /* RISC-V Linux native additions to the default linux support. */ class riscv_linux_nat_target final : public linux_nat_target @@ -88,21 +94,35 @@ static void supply_fpregset_regnum (struct regcache *regcache, const prfpregset_t *fpregs, int regnum) { + int flen = register_size (regcache->arch (), RISCV_FIRST_FP_REGNUM); + union + { + const prfpregset_t *fpregs; + const gdb_byte *buf; + } + fpbuf = { .fpregs = fpregs }; int i; if (regnum == -1) { /* We only support the FP registers and FCSR here. */ - for (i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++) - regcache->raw_supply (i, &fpregs->__d.__f[i - RISCV_FIRST_FP_REGNUM]); + for (i = RISCV_FIRST_FP_REGNUM; + i <= RISCV_LAST_FP_REGNUM; + i++, fpbuf.buf += flen) + regcache->raw_supply (i, fpbuf.buf); - regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); } else if (regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM) - regcache->raw_supply (regnum, - &fpregs->__d.__f[regnum - RISCV_FIRST_FP_REGNUM]); + { + fpbuf.buf += flen * (regnum - RISCV_FIRST_FP_REGNUM); + regcache->raw_supply (regnum, fpbuf.buf); + } else if (regnum == RISCV_CSR_FCSR_REGNUM) - regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + { + fpbuf.buf += flen * (RISCV_LAST_FP_REGNUM - RISCV_FIRST_FP_REGNUM + 1); + regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); + } } /* Copy all floating point registers from regset FPREGS into REGCACHE. */ @@ -145,19 +165,35 @@ void fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregs, int regnum) { + int flen = register_size (regcache->arch (), RISCV_FIRST_FP_REGNUM); + union + { + prfpregset_t *fpregs; + gdb_byte *buf; + } + fpbuf = { .fpregs = fpregs }; + int i; + if (regnum == -1) { /* We only support the FP registers and FCSR here. */ - for (int i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++) - regcache->raw_collect (i, &fpregs->__d.__f[i - RISCV_FIRST_FP_REGNUM]); + for (i = RISCV_FIRST_FP_REGNUM; + i <= RISCV_LAST_FP_REGNUM; + i++, fpbuf.buf += flen) + regcache->raw_collect (i, fpbuf.buf); - regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); } else if (regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM) - regcache->raw_collect (regnum, - &fpregs->__d.__f[regnum - RISCV_FIRST_FP_REGNUM]); + { + fpbuf.buf += flen * (regnum - RISCV_FIRST_FP_REGNUM); + regcache->raw_collect (regnum, fpbuf.buf); + } else if (regnum == RISCV_CSR_FCSR_REGNUM) - regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + { + fpbuf.buf += flen * (RISCV_LAST_FP_REGNUM - RISCV_FIRST_FP_REGNUM + 1); + regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); + } } /* Return a target description for the current target. */ @@ -165,32 +201,9 @@ fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregs, const struct target_desc * riscv_linux_nat_target::read_description () { - struct riscv_gdbarch_features features; - struct iovec iov; - elf_fpregset_t regs; - int tid; - - /* Figuring out xlen is easy. */ - features.xlen = sizeof (elf_greg_t); - - tid = inferior_ptid.lwp (); - - iov.iov_base = ®s; - iov.iov_len = sizeof (regs); - - /* Can we fetch the f-registers? */ - if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, - (PTRACE_TYPE_ARG3) &iov) == -1) - features.flen = 0; /* No f-registers. */ - else - { - /* TODO: We need a way to figure out the actual length of the - f-registers. We could have 64-bit x-registers, with 32-bit - f-registers. For now, just assumed xlen and flen match. */ - features.flen = features.xlen; - } - - return riscv_create_target_description (features); + const struct riscv_gdbarch_features features + = riscv_linux_read_features (inferior_ptid.lwp ()); + return riscv_lookup_target_description (features); } /* Fetch REGNUM (or all registers if REGNUM == -1) from the target @@ -228,7 +241,9 @@ riscv_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum) elf_fpregset_t regs; iov.iov_base = ®s; - iov.iov_len = sizeof (regs); + iov.iov_len = ELF_NFPREG * register_size (regcache->arch (), + RISCV_FIRST_FP_REGNUM); + gdb_assert (iov.iov_len <= sizeof (regs)); if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, (PTRACE_TYPE_ARG3) &iov) == -1) @@ -289,7 +304,9 @@ riscv_linux_nat_target::store_registers (struct regcache *regcache, int regnum) elf_fpregset_t regs; iov.iov_base = ®s; - iov.iov_len = sizeof (regs); + iov.iov_len = ELF_NFPREG * register_size (regcache->arch (), + RISCV_FIRST_FP_REGNUM); + gdb_assert (iov.iov_len <= sizeof (regs)); if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, (PTRACE_TYPE_ARG3) &iov) == -1)