go-delve/delve · error

Undefined return address at %#x

Error message

Undefined return address at %#x

What it means

After evaluating DWARF rules for all registers, Delve reads the return-address register (RetAddrReg). If that rule produced no register (undefined), the function's return address cannot be determined and the stack walk must stop. Error is raised at the PC where the undefined rule was found.

Source

Thrown at pkg/proc/stack.go:767

	// $GDB_SOURCE/dwarf2/frame.c
	callFrameRegs.AddReg(callFrameRegs.SPRegNum, cfareg)

	for i, regRule := range framectx.Regs {
		if logflags.Stack() {
			logger.Debugf("\t%s rule %s ", it.bi.Arch.RegnumToString(i), ruleString(&regRule, it.bi.Arch.RegnumToString))
		}
		reg, err := it.executeFrameRegRule(i, regRule, it.regs.CFA)
		if reg != nil {
			logger.Debugf("\t\t-> %#x", reg.Uint64Val)
		} else {
			logger.Debugf("\t\t-> nothing (%v)", err)
		}
		callFrameRegs.AddReg(i, reg)
		if i == framectx.RetAddrReg {
			if reg == nil {
				if err == nil {
					//lint:ignore ST1005 backwards compatibility
					err = fmt.Errorf("Undefined return address at %#x", it.pc)
				}
				it.err = err
			} else {
				ret = reg.Uint64Val
				// On systems which use a link register to store the return address of a function,
				// certain leaf functions may not have correct DWARF information present in the
				// .debug_frame FDE when unwinding after a fatal signal. This is due to the fact
				// that runtime.sigpanic inserts a frame to make it look like the function which
				// triggered the signal called runtime.sigpanic directly, making the value of the
				// link register unreliable. Instead, treat it as a non-leaf function and read the
				// return address from the stack. For more details, see:
				// https://github.com/golang/go/issues/63862#issuecomment-1802672629.
				if it.frame.Call.Fn != nil && it.frame.Call.Fn.Name == "runtime.sigpanic" && it.bi.Arch.usesLR {
					buf := make([]byte, 8)
					_, err := it.mem.ReadMemory(buf, uint64(it.regs.CFA))
					if err != nil {
						it.err = err
					}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Treat this as end-of-stack if it occurs at the outermost frame (normal terminator in some cases)
  2. Rebuild with an up-to-date Go toolchain and without stripping debug info
  3. Update Delve to get improved Go runtime CFI handling
  4. Skip the broken frame manually in tooling instead of full-stack iteration

Example fix

null
Defensive patterns

Strategy: fallback

Try / catch

frames, err := iterateFrames(); if err != nil && strings.Contains(err.Error(), "Undefined return address") { /* use frames already collected; at outermost frame this is normal termination */ }

Prevention

When it happens

Trigger: advanceRegsDWARF on a frame whose DWARF CFI marks the return address register undefined — typical for frame-less leaf functions or the outermost (start) function, or when CFI for the PC is missing so the retained register is nil.

Common situations: Walking past the bottom of the stack into runtime.startup assembly; debugging optimized/assembly functions with incomplete DWARF; version mismatch where Go emitted CFI that Delve's parser treats as undefined.

Related errors


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