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
- Pass a non-nil MemoryReader (the target process) to ExecuteStackProgram
- Or resolve the expression in a context that provides memory access (e.g., via proc.Variable evaluation instead of raw DWARF execution)
- 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
- Always pass a MemoryReader when evaluating expressions from live targets
- Know which attributes may contain deref ops before choosing the evaluation path
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
- ErrStackUnderflow
- ErrStackIndexOutOfBounds
- empty OP stack
- could not read %d bytes from address %#x: %v
- could not retrieve CFA for current PC
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/ee5aa7a5e9041e3b.
Report an issue: GitHub.