{"record":{"id":"ee5aa7a5e9041e3b","repo":"go-delve/delve","slug":"errmemoryreadunavailable","errorCode":"ErrMemoryReadUnavailable","errorMessage":"memory read unavailable","messagePattern":"memory read unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/dwarf/op/op.go","lineNumber":55,"sourceCode":"\tSize  int\n\tKind  PieceKind\n\tVal   uint64\n\tBytes []byte\n}\n\n// PieceKind describes the kind of a piece.\ntype PieceKind uint8\n\nconst (\n\tAddrPiece PieceKind = iota // The piece is stored in memory, Val is the address\n\tRegPiece                   // The piece is stored in a register, Val is the register number\n\tImmPiece                   // The piece is an immediate value, Val or Bytes is the value\n)\n\nvar (\n\tErrStackUnderflow        = errors.New(\"DWARF stack underflow\")\n\tErrStackIndexOutOfBounds = errors.New(\"DWARF stack index out of bounds\")\n\tErrMemoryReadUnavailable = errors.New(\"memory read unavailable\")\n)\n\nconst arbitraryExecutionLimitFactor = 10\n\n// ExecuteStackProgram executes a DWARF location expression and returns\n// either an address (int64), or a slice of Pieces for location expressions\n// that don't evaluate to an address (such as register and composite expressions).\nfunc ExecuteStackProgram(regs DwarfRegisters, instructions []byte, ptrSize int, readMemory ReadMemoryFunc) (int64, []Piece, error) {\n\tctxt := &context{\n\t\tbuf:            bytes.NewBuffer(instructions),\n\t\tprog:           instructions,\n\t\tstack:          make([]int64, 0, 3),\n\t\tDwarfRegisters: regs,\n\t\tptrSize:        ptrSize,\n\t\treadMemory:     readMemory,\n\t}\n\n\tfor tick := 0; tick < len(instructions)*arbitraryExecutionLimitFactor; tick++ {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/dwarf/op/op.go#L37-L73","documentation":"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.","triggerScenarios":"Calling op.ExecuteStackProgram with a nil memory-reader argument on an expression that contains DW_OP_deref-style deref operations.","commonSituations":"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.","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"],"exampleFix":"// before\naddr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{StaticBase: staticBase}, instr, ptrSize, nil)\n// after\naddr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{StaticBase: staticBase}, instr, ptrSize, memReader)","handlingStrategy":"validation","validationCode":"if memReader == nil && bytes.Contains(instr, []byte{0x16}) /* DW_OP_deref */ { /* need memory access */ }","typeGuard":null,"tryCatchPattern":"if errors.Is(err, op.ErrMemoryReadUnavailable) { /* return address-only result */ }","preventionTips":["Always pass a MemoryReader when evaluating expressions from live targets","Know which attributes may contain deref ops before choosing the evaluation path"],"tags":["dwarf","memory-read","expression-evaluation"],"backgroundTag":"memory-read-unavailable","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}