{"record":{"id":"dc50fb71ba6f5cc1","repo":"go-delve/delve","slug":"changing-register-d-not-implemented","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_arm64_arch.go","lineNumber":177,"sourceCode":"\t\t\tr.Regs.Regs[regNum-regnum.ARM64_X0] = reg.Uint64Val\n\t\t\treturn false, nil\n\n\t\tcase regNum >= regnum.ARM64_V0 && regNum <= regnum.ARM64_V0+30:\n\t\t\tif r.loadFpRegs != nil {\n\t\t\t\terr := r.loadFpRegs(r)\n\t\t\t\tr.loadFpRegs = nil\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn false, err\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti := regNum - regnum.ARM64_V0\n\t\t\treg.FillBytes()\n\t\t\tcopy(r.Fpregset[16*i:], reg.Bytes)\n\t\t\treturn true, nil\n\n\t\tdefault:\n\t\t\treturn false, fmt.Errorf(\"changing register %d not implemented\", regNum)\n\t\t}\n\t}\n}\n\ntype ARM64PtraceFpRegs struct {\n\tVregs []byte\n\tFpsr  uint32\n\tFpcr  uint32\n}\n\nconst _ARM_FP_REGS_LENGTH = 512\n\nfunc (fpregs *ARM64PtraceFpRegs) Decode() (regs []proc.Register) {\n\tfor i := 0; i < len(fpregs.Vregs); i += 16 {\n\t\tregs = proc.AppendBytesRegister(regs, fmt.Sprintf(\"V%d\", i/16), fpregs.Vregs[i:i+16])\n\t}\n\treturn\n}","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/linutil/regs_arm64_arch.go#L159-L195","documentation":"The arm64 SetReg implementation covers only a fixed subset of registers (GPRs and V0-V31 vector registers). Any register number falling through to the default case has no write path implemented, so the request is rejected.","triggerScenarios":"Calling SetReg on Linux/arm64 with a register number that is neither a handled general-purpose register nor within ARM64_V0..V0+31 (e.g. FPSR, FPCR, or a bogus/out-of-range regnum).","commonSituations":"Trying to modify arm64 floating-point status/control registers or system registers via the debugger; porting code that assumed x86-style full register writability.","solutions":["Restrict register writes to GPRs and V0-V31 on arm64","Handle FPSR/FPCR writes through ptrace GETFPREGS/SETFPREGS at the native backend level if needed","Verify the regnum constant is a valid ARM64 register for the intended set"],"exampleFix":"// before\nthread.SetReg(regnum.ARM64_FPSR, reg) // not implemented\n// after\nif regnum.ARM64_V0 <= regNum && regNum <= regnum.ARM64_V0+31 {\n    thread.SetReg(regNum, reg)\n} else {\n    return fmt.Errorf(\"cannot set register %d on arm64\", regNum)\n}","handlingStrategy":"validation","validationCode":"supported := regNum <= regnum.ARM64_R30 || (regNum >= regnum.ARM64_V0 && regNum <= regnum.ARM64_V0+31)\nif !supported {\n    return fmt.Errorf(\"register %d not settable on arm64\", regNum)\n}","typeGuard":"func isSettableARM64(regNum uint64) bool {\n    return regNum <= 30 || (regNum >= regnum.ARM64_V0 && regNum <= regnum.ARM64_V0+31)\n}","tryCatchPattern":"if _, err := thread.SetReg(regNum, reg); err != nil {\n    if strings.Contains(err.Error(), \"not implemented\") {\n        return fmt.Errorf(\"arm64 register %d cannot be modified\", regNum)\n    }\n    return err\n}","preventionTips":["Only write GPRs and V0-V31 on arm64","Treat FPSR/FPCR/system registers as read-only unless the backend adds support","Test register writes per-architecture before enabling the feature in tooling"],"tags":["go","registers","arm64","ptrace"],"backgroundTag":"register-not-settable","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}