go-delve/delve · error

ebpf composite memory

Error message

ebpf composite memory: %w

What it means

This error wraps a failure from CreateCompositeMemory while Delve is loading a variable captured by an eBPF uprobe tracepoint. When an argument value is spread across DWARF location pieces (registers/stack fragments), Delve reassembles them into a CompositeMemory; if the pieces are inconsistent with the type's byte size or the architecture, the variable is returned with Unreadable set to this wrapped error.

Solutions

  1. Check that the traced function's argument type is one of the eBPF-supported kinds (int, uint, bool, float, complex, string, pointer, slice); avoid tracing structs/maps/chans/interfaces/funcs/arrays
  2. Rebuild the eBPF object with 'make build-ebpf-object' using the supported clang-22 builder image so register capture matches the expected layout
  3. Verify UProbeArgMap piece offsets/sizes produced from DWARF match the type's ByteSize for the target arch
  4. If floats appear in XMM registers (DWARF regnum >= 17), accept them as unreadable or restructure the traced function signature

Example fix

// before: tracing a struct arg which has no single-register representation
//   func worker(s MyStruct)
// after: trace scalar fields instead or pass by pointer and read in the test
//   func worker(s *MyStruct) // pointer kind is supported by ebpf backend
Defensive patterns

Strategy: fallback

Validate before calling

// before tracing, check argument kinds are ebpf-supported
func ebpfSupported(dt godwarf.Type) bool {
    switch dt.Common().ReflectKind {
    case reflect.Int, reflect.Uint, reflect.Bool, reflect.Float32,
        reflect.Float64, reflect.Complex64, reflect.Complex128,
        reflect.String, reflect.Ptr:
        return true
    }
    return false
}

Type guard

func isUnreadable(v *proc.Variable) bool { return v != nil && v.Unreadable != nil }

Try / catch

v, err := dbg.GetBufferedTracepoints(...)
if v != nil {
    for _, tv := range v {
        if tv.Unreadable != nil {
            log.Printf("tracepoint arg unreadable: %v", tv.Unreadable)
            continue
        }
    }
}

Prevention

When it happens

Trigger: Calling GetBufferedTracepoints (or any code path that loads eBPF-buffered tracepoint arguments) where ip.Pieces do not cover exactly the RealType byte size for a composite (struct/array/slice/float) argument, or the captured data length mismatches what CreateCompositeMemory expects for binInfo.Arch.

Common situations: Tracing functions whose argument types are not fully supported by the eBPF backend (structs, arrays, or floats in XMM registers which uprobes cannot read); stale .o eBPF object built with an old clang producing wrong register capture; architecture mismatches between the traced binary and the loaded eBPF program.

Related errors


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

Appendix: source

Thrown at pkg/proc/target.go:520

		v.Len = ip.Len
		v.Base = ip.Base
		v.Addr = ip.Addr
		v.Kind = ip.Kind
		v.bi = t.BinInfo()

		if ip.Unreadable != nil {
			v.Unreadable = ip.Unreadable
			return v
		}
		if v.RealType == nil {
			v.Unreadable = errors.New("type not supported by ebpf")
			return v
		}

		cachedMem := CreateLoadedCachedMemory(ip.Data)
		compMem, compErr := CreateCompositeMemory(cachedMem, t.BinInfo().Arch, op.DwarfRegisters{}, ip.Pieces, ip.RealType.Common().ByteSize)
		if compErr != nil {
			v.Unreadable = fmt.Errorf("ebpf composite memory: %w", compErr)
			return v
		}
		v.mem = compMem

		v.loadValue(cfg)

		return v
	}
	for _, tp := range tracepoints {
		r := &UProbeTraceResult{}
		r.FnAddr = tp.FnAddr
		r.GoroutineID = tp.GoroutineID
		r.IsRet = tp.IsRet
		for _, ip := range tp.InputParams {
			v := convertInputParamToVariable(ip)
			r.InputParams = append(r.InputParams, v)
		}
		for _, ip := range tp.ReturnParams {

View on GitHub (pinned to a23773e6c3)