go-delve/delve · error

panic(err)

Error message

panic(err)

What it means

The DWARF CFI opcode interpreter in pkg/dwarf/frame/table.go calls panic(err) when the underlying byte buffer returns an error while reading an opcode operand in the `offset` (DW_CFA_offset-like) instruction handler. This means the CFI instruction stream was truncated or the buffer was exhausted mid-instruction. It signals corrupt, truncated, or improperly parsed .eh_frame/.debug_frame data rather than an expected runtime condition.

Source

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

func advanceloc2(frame *FrameContext) {
	var delta uint16
	binary.Read(frame.buf, frame.order, &delta)

	frame.loc += uint64(delta) * frame.codeAlignment
}

func advanceloc4(frame *FrameContext) {
	var delta uint32
	binary.Read(frame.buf, frame.order, &delta)

	frame.loc += uint64(delta) * frame.codeAlignment
}

func offset(frame *FrameContext) {
	b, err := frame.buf.ReadByte()
	if err != nil {
		panic(err)
	}

	var (
		reg       = b & low_6_offset
		offset, _ = leb128.DecodeUnsigned(frame.buf)
	)

	frame.Regs[uint64(reg)] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
}

func restore(frame *FrameContext) {
	b, err := frame.buf.ReadByte()
	if err != nil {
		panic(err)
	}

	reg := uint64(b & low_6_offset)
	oldrule, ok := frame.initialRegs[reg]

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Verify the binary/core file is complete and its .eh_frame/.debug_frame sections are not truncated (re-obtain the file or re-dump the core).
  2. Check the upstream code that computes the instruction length/buffer for the frame entry; a wrong length makes buf end mid-instruction.
  3. Update Delve: newer versions may return an error instead of panicking on malformed CFI data.
  4. If parsing untrusted binaries, wrap CFI parsing in recover() and surface a descriptive error.

Example fix

// before (table.go)
b, err := frame.buf.ReadByte()
if err != nil {
	panic(err)
}
// after
type frameParseError struct{ msg string; err error }
func offset(frame *FrameContext) (err error) {
	b, err := frame.buf.ReadByte()
	if err != nil {
		return fmt.Errorf("malformed CFI: reading offset opcode: %w", err)
	}
	return nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: check section completeness before parsing CFI
if len(debugFrameData) == 0 || uint64(len(debugFrameData)) < fdeLength {
	return errors.New("truncated .debug_frame data")
}

Try / catch

// Go
go func() {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("malformed CFI instruction stream: %v", r)
		}
	}()
	buildFrameTable(buf)
}()

Prevention

When it happens

Trigger: Executing the `offset` CFI opcode handler when frame.buf.ReadByte() fails because the instruction stream ends before the register byte (and following ULEB128 offset) can be fully read — e.g. a truncated .debug_frame section, a misaligned instruction stream, or advancing a reader past its end.

Common situations: Parsing core dumps or stripped binaries with damaged/truncated DWARF sections; a length/count mismatch upstream that slices the instruction buffer too short; hand-crafted or fuzzed ELF files fed to the frame parser.

Related errors


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