go-delve/delve · error

could not restore RFLAGS register: %v

Error message

could not restore RFLAGS register: %v

What it means

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.

Source

Thrown at pkg/proc/fncall.go:883

		if err := setPC(thread, pc); err != nil {
			fncall.err = fmt.Errorf("could not restore PC: %v", err)
		}
		if err := setSP(thread, sp); err != nil {
			fncall.err = fmt.Errorf("could not restore SP: %v", err)
		}
		fncallLog("stepping thread %d", thread.ThreadID())
		if err := stepInstructionOut(callScope.callCtx.grp, p, thread, fncall.debugCallName, fncall.debugCallName); err != nil {
			fncall.err = fmt.Errorf("could not step out of %s: %v", fncall.debugCallName, err)
		}
		if bi.Arch.Name == "amd64" {
			// The tail of debugCallV2 corrupts the state of RFLAGS, we must restore
			// it one extra time after stepping out of it.
			// See https://github.com/go-delve/delve/issues/2985 and
			// TestCallInjectionFlagCorruption
			rflags := bi.Arch.RegistersToDwarfRegisters(0, fncall.savedRegs).Uint64Val(regnum.AMD64_Rflags)
			err := thread.SetReg(regnum.AMD64_Rflags, op.DwarfRegisterFromUint64(rflags))
			if err != nil {
				fncall.err = fmt.Errorf("could not restore RFLAGS register: %v", err)
			}
		}
		return true

	case debugCallRegReadReturn: // 1
		// read return arguments from stack
		stack.callInjectionContinue = true
		if fncall.panicvar != nil || fncall.err != nil {
			break
		}
		retScope, err := ThreadScope(p, thread)
		if err != nil {
			fncall.err = fmt.Errorf("could not get return values: %v", err)
			break
		}

		// pretend we are still inside the function we called
		fakeFunctionEntryScope(retScope, fncall.fn, int64(regs.SP()), regs.SP()-uint64(bi.Arch.PtrSize()))

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Verify the process is alive; restart the session if not
  2. Retry the call injection — transient register-write failures may clear
  3. Use a backend that supports SetReg (native) rather than core dumps
  4. Report persistent amd64 RFLAGS write failures to Delve issue tracker (see issue #2985)
Defensive patterns

Strategy: try-catch

Validate before calling

// amd64 only: confirm backend supports SetReg before call injection
// (native backend does; core dumps do not)

Try / catch

err := dbg.CallFunction(scope, fn, args)
if err != nil && strings.Contains(err.Error(), "could not restore RFLAGS") {
	// flags may be stale: restart session or re-issue the call
}

Prevention

When it happens

Trigger: funcCallStep, on the amd64 path after stepping out of debugCallV2, calls thread.SetReg(regnum.AMD64_Rflags, ...) and it returns an error.

Common situations: 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.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/b4a4775fda059dc7. Report an issue: GitHub.