{"record":{"id":"b4a4775fda059dc7","repo":"go-delve/delve","slug":"could-not-restore-rflags-register-v","errorCode":null,"errorMessage":"could not restore RFLAGS register: %v","messagePattern":"could not restore RFLAGS register: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/fncall.go","lineNumber":883,"sourceCode":"\t\tif err := setPC(thread, pc); err != nil {\n\t\t\tfncall.err = fmt.Errorf(\"could not restore PC: %v\", err)\n\t\t}\n\t\tif err := setSP(thread, sp); err != nil {\n\t\t\tfncall.err = fmt.Errorf(\"could not restore SP: %v\", err)\n\t\t}\n\t\tfncallLog(\"stepping thread %d\", thread.ThreadID())\n\t\tif err := stepInstructionOut(callScope.callCtx.grp, p, thread, fncall.debugCallName, fncall.debugCallName); err != nil {\n\t\t\tfncall.err = fmt.Errorf(\"could not step out of %s: %v\", fncall.debugCallName, err)\n\t\t}\n\t\tif bi.Arch.Name == \"amd64\" {\n\t\t\t// The tail of debugCallV2 corrupts the state of RFLAGS, we must restore\n\t\t\t// it one extra time after stepping out of it.\n\t\t\t// See https://github.com/go-delve/delve/issues/2985 and\n\t\t\t// TestCallInjectionFlagCorruption\n\t\t\trflags := bi.Arch.RegistersToDwarfRegisters(0, fncall.savedRegs).Uint64Val(regnum.AMD64_Rflags)\n\t\t\terr := thread.SetReg(regnum.AMD64_Rflags, op.DwarfRegisterFromUint64(rflags))\n\t\t\tif err != nil {\n\t\t\t\tfncall.err = fmt.Errorf(\"could not restore RFLAGS register: %v\", err)\n\t\t\t}\n\t\t}\n\t\treturn true\n\n\tcase debugCallRegReadReturn: // 1\n\t\t// read return arguments from stack\n\t\tstack.callInjectionContinue = true\n\t\tif fncall.panicvar != nil || fncall.err != nil {\n\t\t\tbreak\n\t\t}\n\t\tretScope, err := ThreadScope(p, thread)\n\t\tif err != nil {\n\t\t\tfncall.err = fmt.Errorf(\"could not get return values: %v\", err)\n\t\t\tbreak\n\t\t}\n\n\t\t// pretend we are still inside the function we called\n\t\tfakeFunctionEntryScope(retScope, fncall.fn, int64(regs.SP()), regs.SP()-uint64(bi.Arch.PtrSize()))","sourceCodeStart":865,"sourceCodeEnd":901,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/fncall.go#L865-L901","documentation":"On amd64, the tail of runtime.debugCallV2 corrupts the RFLAGS register, so Delve restores it one extra time from the saved register set. This error is raised when writing the RFLAGS register back to the thread fails.","triggerScenarios":"funcCallStep, on the amd64 path after stepping out of debugCallV2, calls thread.SetReg(regnum.AMD64_Rflags, ...) and it returns an error.","commonSituations":"Thread died between the step-out and the register write; ptrace/GETREGSET failures on Linux; gdbserial backends that reject partial register writes; core dump backends that are read-only.","solutions":["Verify the process is alive; restart the session if not","Retry the call injection — transient register-write failures may clear","Use a backend that supports SetReg (native) rather than core dumps","Report persistent amd64 RFLAGS write failures to Delve issue tracker (see issue #2985)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// amd64 only: confirm backend supports SetReg before call injection\n// (native backend does; core dumps do not)","typeGuard":null,"tryCatchPattern":"err := dbg.CallFunction(scope, fn, args)\nif err != nil && strings.Contains(err.Error(), \"could not restore RFLAGS\") {\n\t// flags may be stale: restart session or re-issue the call\n}\n","preventionTips":["Use a writable backend (native) on amd64 for injected calls","Keep the process alive through the whole call protocol","Retry once — RFLAGS restore failures are often transient","See delve issue #2985 for known RFLAGS corruption handling"],"tags":["go","fncall","amd64","rflags","registers"],"backgroundTag":"register-restore-failed","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}