{"record":{"id":"8a2509bc3f051cfd","repo":"go-delve/delve","slug":"failed-to-set-fp-registers-v","errorCode":null,"errorMessage":"failed to set FP registers: %v","messagePattern":"failed to set FP registers: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/native/ptrace_freebsd_amd64.go","lineNumber":84,"sourceCode":"\nfunc ptraceGetRegset(id int) (*amd64util.AMD64Xstate, error) {\n\tvar regset amd64util.AMD64Xstate\n\tret, err := C.ptrace(C.PT_GETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), C.int(0))\n\tif ret != 0 {\n\t\treturn nil, fmt.Errorf(\"failed to get FP registers: %v\", err)\n\t}\n\tregset.Xsave, err = ptraceGetXsave(id)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\terr = amd64util.AMD64XstateRead(regset.Xsave, false, &regset, cpuid.AMD64XstateZMMHi256Offset())\n\treturn &regset, err\n}\n\nfunc ptraceSetRegset(id int, regset *amd64util.AMD64Xstate) error {\n\tret, err := C.ptrace(C.PT_SETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), C.int(0))\n\tif ret != 0 {\n\t\treturn fmt.Errorf(\"failed to set FP registers: %v\", err)\n\t}\n\tif regset.Xsave != nil {\n\t\treturn ptraceSetXsave(id, regset.Xsave)\n\t}\n\treturn nil\n}\n","sourceCodeStart":66,"sourceCodeEnd":91,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/native/ptrace_freebsd_amd64.go#L66-L91","documentation":"ptraceSetRegset writes the FP register block with PT_SETFPREGS on FreeBSD/amd64, then optionally the xstate via PT_SETXSTATE. Failure of PT_SETFPREGS is wrapped as 'failed to set FP registers'. The kernel rejected the FP state write for this thread.","triggerScenarios":"Calling register-setting APIs (e.g. nativeThread.SetReg on FP/SSE registers, SetPC paths that restore full state) on a dead/stale tid, with a malformed regset, or without ptrace permission.","commonSituations":"Setting FP registers after the debuggee thread exited; hardware/kernel mismatch making the FP area invalid; writing while the process is not in a stopped state acceptable to ptrace.","solutions":["Verify the thread is stopped and alive before writing registers","Re-fetch a fresh regset (PT_GETFPREGS), modify only needed fields, then write back","Check ptrace permissions (root/same-UID, jail/securelevel constraints)","If the write races with thread exit, detect ESRCH and treat as thread-dead rather than retrying blindly"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure thread stopped and alive before write\nif !isThreadAlive(dbp, id) {\n\treturn fmt.Errorf(\"thread %d exited; cannot set FP registers\", id)\n}\nif !isStopped(dbp) {\n\treturn fmt.Errorf(\"process must be stopped to set registers\")\n}","typeGuard":null,"tryCatchPattern":"if err := ptraceSetRegset(id, regset); err != nil {\n\tif strings.Contains(err.Error(), \"failed to set FP registers\") {\n\t\t// refresh regset from the live thread and retry once\n\t\tfresh, ferr := ptraceGetRegset(id)\n\t\tif ferr == nil {\n\t\t\treturn ptraceSetRegset(id, fresh)\n\t\t}\n\t}\n\treturn err\n}","preventionTips":["Always write a regset freshly read from the same thread","Only write registers while the target is stopped","Check for ESRCH and drop the thread from the cache on failure"],"tags":["freebsd","ptrace","floating-point","registers"],"backgroundTag":"ptrace-fpregs-write-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}