{"record":{"id":"1ac3edb7f9313c77","repo":"go-delve/delve","slug":"changing-register-d-not-implemented-1ac3ed","errorCode":null,"errorMessage":"changing register %d not implemented","messagePattern":"changing register (.+?) not implemented","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/linutil/regs_riscv64_arch.go","lineNumber":356,"sourceCode":"\t}\n\n\tswitch {\n\tcase regNum >= regnum.RISCV64_F0 && regNum <= regnum.RISCV64_F31:\n\t\tif r.loadFpRegs != nil {\n\t\t\terr := r.loadFpRegs(r)\n\t\t\tr.loadFpRegs = nil\n\t\t\tif err != nil {\n\t\t\t\treturn false, err\n\t\t\t}\n\t\t}\n\n\t\ti := regNum - regnum.RISCV64_F0\n\t\treg.FillBytes()\n\t\tcopy(r.Fpregset[8*i:], reg.Bytes)\n\t\treturn true, nil\n\n\tdefault:\n\t\treturn false, fmt.Errorf(\"changing register %d not implemented\", regNum)\n\t}\n}\n\n// RISCV64PtraceFpRegs is refer to the definition of struct __riscv_d_ext_state in the kernel ptrace.h\ntype RISCV64PtraceFpRegs struct {\n\tFregs []byte\n\tFcsr  uint32\n}\n\nconst _RISCV64_FPREGSET_LENGTH = (32 * 8)\n\nfunc (fpregs *RISCV64PtraceFpRegs) Decode() (regs []proc.Register) {\n\tfor i := 0; i < len(fpregs.Fregs); i += 8 {\n\t\tname := fmt.Sprintf(\"F%d\", (i / 8))\n\t\tvalue := fpregs.Fregs[i : i+8]\n\t\tregs = proc.AppendBytesRegister(regs, name, value)\n\t}\n","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/linutil/regs_riscv64_arch.go#L338-L374","documentation":"The riscv64 SetReg implementation covers integer registers and the F0-F31 floating-point registers; any other register number hits the default branch and is rejected as not implemented.","triggerScenarios":"Calling SetReg on Linux/riscv64 with a register number outside the implemented GPR set and outside RISCV64_F0..F0+31 (e.g. FCSR, CSR registers).","commonSituations":"Attempting to write riscv64 control/status registers via the debugger; register constants from another ISA leaking into the riscv64 path.","solutions":["Only write GPRs and F0-F31 via SetReg on riscv64","Handle FCSR writes through the native backend's ptrace register sets if needed","Check regnum ranges in the caller before invoking SetReg"],"exampleFix":"// before\nthread.SetReg(regnum.RISCV64_FCSR, reg) // not implemented\n// after\nif regnum.RISCV64_F0 <= regNum && regNum <= regnum.RISCV64_F0+31 {\n    thread.SetReg(regNum, reg)\n} else {\n    return fmt.Errorf(\"cannot set register %d on riscv64\", regNum)\n}","handlingStrategy":"validation","validationCode":"supported := isGPR(regNum) || (regNum >= regnum.RISCV64_F0 && regNum <= regnum.RISCV64_F0+31)\nif !supported {\n    return fmt.Errorf(\"register %d not settable on riscv64\", regNum)\n}","typeGuard":"func isSettableRISCV64(regNum uint64) bool {\n    return isGPR(regNum) || (regNum >= regnum.RISCV64_F0 && regNum <= regnum.RISCV64_F0+31)\n}","tryCatchPattern":"if _, err := thread.SetReg(regNum, reg); err != nil {\n    if strings.Contains(err.Error(), \"not implemented\") {\n        return fmt.Errorf(\"riscv64 register %d cannot be modified\", regNum)\n    }\n    return err\n}","preventionTips":["Only write integer and F0-F31 registers on riscv64","Treat FCSR/CSRs as read-only through SetReg","Validate regnum against the riscv64 package constants"],"tags":["go","registers","riscv64","ptrace"],"backgroundTag":"register-not-settable","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}