go-delve/delve · critical

Could not read byte

Error message

Could not read byte

What it means

advanceloc panics when it cannot read the delta byte for a DW_CFA_advance_loc1-style one-byte location advance. The frame instruction stream ended exactly where an operand byte was expected, meaning the CFI program is truncated relative to its declared length.

Solutions

  1. Verify the binary/core integrity and re-acquire it from a trusted source
  2. Check that the binary and core dump match (same build ID)
  3. Report to delve maintainers — this should be an error return, not a panic
  4. Recover from the panic at the call site and skip frame unwinding for that frame

Example fix

// before
frames, err := t.ExecuteUntilPC(pc) // panic on malformed stream
// after
func safeFrames(t *frame.Table, pc uint64) (frames []frame.Frame, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("invalid CFI stream: %v", r)
        }
    }()
    fde, e := t.ExecuteUntilPC(pc)
    if e != nil {
        return nil, e
    }
    frames, err = fde.EstablishFrame(t.CIE) // illustrative decode
    return
}
Defensive patterns

Strategy: try-catch

Try / catch

func safeAdvance(t *frame.FrameDescriptionEntry) (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("truncated CFI stream: %v", r)
        }
    }()
    // trigger the decode path
    return nil
}

Prevention

When it happens

Trigger: Parsing a frame description entry whose declared length extends past the end of the section data; corrupted .debug_frame/.eh_frame sections; decode bugs where buf was not rewound between CFI programs.

Common situations: Analyzing a truncated or partially downloaded binary; core dump files whose mapped frame sections are incomplete; third-party binaries with hand-written assembler frames.

Related errors


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

Appendix: source

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

		instruction = DW_CFA_restore
		restore = true
	}

	if restore {
		// Restore the last byte as it actually contains the argument for the opcode.
		err := buf.UnreadByte()
		if err != nil {
			panic("Could not unread byte")
		}
	}

	return fnlookup[instruction]
}

func advanceloc(frame *FrameContext) {
	b, err := frame.buf.ReadByte()
	if err != nil {
		panic("Could not read byte")
	}

	delta := b & low_6_offset
	frame.loc += uint64(delta) * frame.codeAlignment
}

func advanceloc1(frame *FrameContext) {
	delta, err := frame.buf.ReadByte()
	if err != nil {
		panic("Could not read byte")
	}

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

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

View on GitHub (pinned to a23773e6c3)