go-delve/delve · critical

Could not read from instruction buffer

Error message

Could not read from instruction buffer

What it means

executeDwarfInstruction panics when the DWARF CFI instruction buffer is exhausted mid-decode: buf.ReadByte() failed so there is no opcode byte to dispatch on. This indicates a truncated or malformed .eh_frame/.debug_frame section (or a decode offset bug), and the library surfaces it as a panic rather than an error return.

Source

Thrown at pkg/dwarf/frame/table.go:205

	frame.buf.Truncate(0)
	frame.buf.Write(instructions)

	// We only need to execute the instructions until
	// ctx.loc > ctx.address (which is the address we
	// are currently at in the traced process).
	for frame.address >= frame.loc && frame.buf.Len() > 0 && frame.err == nil {
		executeDwarfInstruction(frame)
	}
	return frame.err
}

func executeDwarfInstruction(frame *FrameContext) {
	if frame.err != nil {
		return
	}
	instruction, err := frame.buf.ReadByte()
	if err != nil {
		panic("Could not read from instruction buffer")
	}

	if instruction == DW_CFA_nop {
		return
	}

	fn := lookupFunc(instruction, frame.buf)

	if fn == nil {
		frame.err = fmt.Errorf("encountered an unexpected DWARF CFA opcode: %#v", instruction)
		return
	}

	fn(frame)
}

func lookupFunc(instruction byte, buf *bytes.Buffer) instruction {
	const high_2_bits = 0xc0

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Regenerate or re-obtain the binary/core file and retry — corruption is the usual cause
  2. Verify the executable and core dump come from the same build and are complete (checksums)
  3. File a bug with the offending binary attached: a panic here is a parser robustness defect and should be recovered/converted to an error upstream
  4. As a caller, wrap ExecuteUntilPC in a recover() until the parser is hardened

Example fix

// caller-side mitigation
// before
fde, err := table.ExecuteUntilPC(pc)
// after
func safeExecute(t *frame.Table, pc uint64) (res *frame.FrameDescriptionEntry, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("malformed frame data: %v", r)
        }
    }()
    return t.ExecuteUntilPC(pc)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify inputs before parsing frame data:
// 1) binary and core exist and are non-empty
fi, err := os.Stat(corePath)
if err != nil || fi.Size() == 0 { return fmt.Errorf("missing/empty core file") }
// 2) match ELF build IDs between executable and core
// (mismatches commonly produce truncated/misread DWARF sections)

Try / catch

func safeExecute(t *frame.Table, pc uint64) (res *frame.FrameDescriptionEntry, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("malformed CFI stream: %v", r)
        }
    }()
    return t.ExecuteUntilPC(pc)
}

Prevention

When it happens

Trigger: Parsing a frame description entry whose CIE/FDE length fields are inconsistent with the actual section data; a corrupt or hand-trimmed binary; a truncated core dump or stripped binary where the frame section was cut short.

Common situations: Analyzing core dumps from mismatched or partially written files; binaries produced by non-Go toolchains or linkers that emit unusual FDE padding; loading symbols from a binary corrupted during download/transfer.

Related errors


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