{"record":{"id":"ba995d60d15088ec","repo":"go-delve/delve","slug":"failed-to-get-fp-registers-v","errorCode":null,"errorMessage":"failed to get FP registers: %v","messagePattern":"failed to get FP registers: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/native/ptrace_freebsd_amd64.go","lineNumber":71,"sourceCode":"\t\treturn nil, fmt.Errorf(\"failed to get xstate: %v\", err)\n\t}\n\treturn xsaveBuf, nil\n}\n\n// ptraceSetXsave sets the X86 XSAVE data for the given tid.\nfunc ptraceSetXsave(tid int, xsaveBuf []byte) error {\n\tret, err := C.ptrace(C.PT_SETXSTATE, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&xsaveBuf[0])), C.int(len(xsaveBuf)))\n\tif ret != 0 {\n\t\treturn fmt.Errorf(\"failed to set xstate: %v\", err)\n\t}\n\treturn nil\n}\n\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","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/native/ptrace_freebsd_amd64.go#L53-L89","documentation":"ptraceGetRegset reads the x87/SSE floating-point register block of a FreeBSD/amd64 thread with PT_GETFPREGS. If the ptrace call fails, the errno is wrapped as 'failed to get FP registers'. This aborts the whole register read since FP registers cannot be fetched.","triggerScenarios":"Reading registers of a thread (nativeThread.Registers -> fpRegisters -> ptraceGetRegset) whose tid no longer exists, when the process is not stopped/attached properly, or when ptrace privileges are missing.","commonSituations":"Debuggee exited or crashed while a register read was in flight; attaching to a process without sufficient permission; a stale cached thread ID after the target execed or forked.","solutions":["Re-check that the process/thread is alive and still traced before reading registers","Re-list threads after process exit/exec and drop stale IDs","Ensure delve has permission to ptrace the target (same UID or root; check securelevel/jail restrictions)","Retry the operation if it raced with a stop event; otherwise let the debugger mark the thread dead"],"exampleFix":"// before\nret, err := C.ptrace(C.PT_GETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), C.int(0))\nif ret != 0 {\n\treturn nil, fmt.Errorf(\"failed to get FP registers: %v\", err)\n}\n// after\nret, err := C.ptrace(C.PT_GETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), C.int(0))\nif ret != 0 {\n\tif errors.Is(err, syscall.ESRCH) {\n\t\treturn nil, fmt.Errorf(\"thread %d exited: %w\", id, err)\n\t}\n\treturn nil, fmt.Errorf(\"failed to get FP registers: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"if dbp.proc == nil || !procAlive(dbp) {\n\treturn fmt.Errorf(\"process not available for FP register read\")\n}\nif !isThreadAlive(dbp, thread.ID) {\n\treturn fmt.Errorf(\"thread %d exited\", thread.ID)\n}","typeGuard":"func fpRegErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"failed to get FP registers\")\n}","tryCatchPattern":"fpregs, err := thread.fpRegisters()\nif fpRegErr(err) {\n\t// GPRs may still be valid; degrade to GPR-only registers\n\treturn thread.Registers(), nil\n}","preventionTips":["Handle ESRCH-style failures as thread-dead rather than retrying","Keep ptrace permissions correct (yama/ptrace_scope, container caps)","Re-enumerate threads after stop events to avoid stale tids"],"tags":["freebsd","ptrace","floating-point","registers","thread-exited"],"backgroundTag":"ptrace-fpregs-read-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}