go-delve/delve · error

could not read DWARF function entry

Error message

could not read DWARF function entry: %v

What it means

Defer.EvalScope reads the DWARF DIE of the wrapper function (scope.Fn) to evaluate AttrFrameBase. The dwarf reader's Seek+Next failed, meaning the DWARF info for that function entry is unreadable — either malformed DWARF, wrong offsets in BinaryInfo, or a truncated .debug_info section.

Solutions

  1. Restart the debug session against the exact current binary (don't rebuild while attached)
  2. Rebuild the target with standard `go build` so DWARF is well-formed
  3. Check disk integrity / re-transfer the binary
  4. Update Delve if the DWARF version is newer than supported

Example fix

// before
# rebuild while dlv attached
go build -o app . && ./app
// after
# stop dlv, rebuild, then relaunch under dlv
dlv exec ./app
Defensive patterns

Strategy: try-catch

Validate before calling

rdr := fn.cu.image.dwarfReader; rdr.Seek(fn.offset); if _, err := rdr.Next(); err != nil { return errors.New("DWARF entry unreadable: reload binary info") }

Try / catch

scope, err := d.EvalScope(t, thread); if err != nil && strings.Contains(err.Error(), "could not read DWARF function entry") { /* restart the debug session against the current binary */ }

Prevention

When it happens

Trigger: Calling Defer.EvalScope when rdr.Next() at scope.Fn.offset errors — corrupted/mismatched DWARF sections, or image whose dwarf reader got invalidated (e.g. binary changed on disk after launch).

Common situations: Binary rebuilt while the debugger was attached (offsets stale); DWARF produced by an unsupported compiler/flags; truncated or corrupted executables; debugging with wrong-arch DWARF.

Related errors


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

Appendix: source

Thrown at pkg/proc/stack.go:1083

		// argument, that's what we use for the value of CFA.
		// For SP we use CFA minus the size of one pointer because that would be
		// the space occupied by pushing the return address on the stack during the
		// CALL.
		scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize)
		scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize()))
	} else {
		// On architectures that have a link register CFA and SP have the same
		// value but the address of the first argument is at CFA+ptrSize so we set
		// CFA to the start of the argument frame minus one pointer size.
		scope.Regs.CFA = int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize - int64(bi.Arch.PtrSize())
		scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(scope.Regs.CFA)
	}

	rdr := scope.Fn.cu.image.dwarfReader
	rdr.Seek(scope.Fn.offset)
	e, err := rdr.Next()
	if err != nil {
		return nil, fmt.Errorf("could not read DWARF function entry: %v", err)
	}
	scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs, scope.Mem)
	scope.Mem = cacheMemory(scope.Mem, uint64(scope.Regs.CFA), int(d.argSz))

	return scope, nil
}

// DeferredFunc returns the deferred function, on Go 1.17 and later unwraps
// any defer wrapper.
func (d *Defer) DeferredFunc(p *Target) (file string, line int, fn *Function) {
	bi := p.BinInfo()
	fn = bi.PCToFunc(d.DwrapPC)
	fn = p.dwrapUnwrap(fn)
	if fn == nil {
		return "", 0, nil
	}
	file, line = bi.EntryLineForFunc(fn)
	return file, line, fn

View on GitHub (pinned to a23773e6c3)