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
- 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).
- Check the upstream code that computes the instruction length/buffer for the frame entry; a wrong length makes buf end mid-instruction.
- Update Delve: newer versions may return an error instead of panicking on malformed CFI data.
- 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
- Only parse complete, unmodified binaries and core dumps
- Validate section lengths against file size before parsing
- Keep Delve updated — panic-on-malformed may become error returns
- Recover() around frame table construction for untrusted inputs
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
- architectural frame rules are unsupported
- Could not read from instruction buffer
- Could not unread byte
- Could not read byte
- Could not parse ULEB128 value
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/3a63565588c55a6a.
Report an issue: GitHub.