go-delve/delve · error

ErrMemoryReadUnavailable

ErrMemoryReadUnavailable

Error message

memory read unavailable

What it means

ErrMemoryReadUnavailable signals that during DWARF expression evaluation (the deref opcode) a memory read was required but no memory reader was supplied. ExecuteStackProgram accepts an optional MemoryReader; when it is nil and derefencing is attempted, this sentinel is returned instead of performing the read.

Source

Thrown at pkg/dwarf/op/op.go:55

	Size  int
	Kind  PieceKind
	Val   uint64
	Bytes []byte
}

// PieceKind describes the kind of a piece.
type PieceKind uint8

const (
	AddrPiece PieceKind = iota // The piece is stored in memory, Val is the address
	RegPiece                   // The piece is stored in a register, Val is the register number
	ImmPiece                   // The piece is an immediate value, Val or Bytes is the value
)

var (
	ErrStackUnderflow        = errors.New("DWARF stack underflow")
	ErrStackIndexOutOfBounds = errors.New("DWARF stack index out of bounds")
	ErrMemoryReadUnavailable = errors.New("memory read unavailable")
)

const arbitraryExecutionLimitFactor = 10

// ExecuteStackProgram executes a DWARF location expression and returns
// either an address (int64), or a slice of Pieces for location expressions
// that don't evaluate to an address (such as register and composite expressions).
func ExecuteStackProgram(regs DwarfRegisters, instructions []byte, ptrSize int, readMemory ReadMemoryFunc) (int64, []Piece, error) {
	ctxt := &context{
		buf:            bytes.NewBuffer(instructions),
		prog:           instructions,
		stack:          make([]int64, 0, 3),
		DwarfRegisters: regs,
		ptrSize:        ptrSize,
		readMemory:     readMemory,
	}

	for tick := 0; tick < len(instructions)*arbitraryExecutionLimitFactor; tick++ {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Pass a non-nil MemoryReader (the target process) to ExecuteStackProgram
  2. Or resolve the expression in a context that provides memory access (e.g., via proc.Variable evaluation instead of raw DWARF execution)
  3. Handle the sentinel with errors.Is and report the address-only value when memory is not available

Example fix

// before
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{StaticBase: staticBase}, instr, ptrSize, nil)
// after
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{StaticBase: staticBase}, instr, ptrSize, memReader)
Defensive patterns

Strategy: validation

Validate before calling

if memReader == nil && bytes.Contains(instr, []byte{0x16}) /* DW_OP_deref */ { /* need memory access */ }

Try / catch

if errors.Is(err, op.ErrMemoryReadUnavailable) { /* return address-only result */ }

Prevention

When it happens

Trigger: Calling op.ExecuteStackProgram with a nil memory-reader argument on an expression that contains DW_OP_deref-style deref operations.

Common situations: Evaluating global/static variable location expressions (AddrFor in pkg/dwarf/reader) where only register context and instructions are passed, but the expression dereferences a pointer.

Related errors


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