func unmarshalBytes(data interface{}, buf []byte) error {
	switch value := data.(type) {
	case unsafe.Pointer:
		sh := &reflect.SliceHeader{  
			Data: uintptr(value),
			Len:  len(buf),
			Cap:  len(buf),
		}
		dst := *(*[]byte)(unsafe.Pointer(sh))
		copy(dst, buf)
		runtime.KeepAlive(value)
		return nil
	case Map, *Map, Program, *Program:
		return fmt.Errorf("can't unmarshal into %T", value)
	case encoding.BinaryUnmarshaler:
		return value.UnmarshalBinary(buf)
	case *string:
		*value = string(buf)
		return nil
	case *[]byte:
		*value = buf
		return nil
	case string:
		return errors.New("require pointer to string")
	case []byte:
		return errors.New("require pointer to []byte")
	default:
		rd := bytes.NewReader(buf)
		if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
			return fmt.Errorf("decoding %T: %v", value, err)
		}
		return nil
	}
}
unmarshalBytes converts a byte buffer into an arbitrary value.

Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
those have special cases that allow more types to be encoded.
package ebpf
import (
	"bytes"
	"encoding"
	"encoding/binary"
	"errors"
	"fmt"
	"reflect"
	"runtime"
	"unsafe"
	"github.com/cilium/ebpf/internal"
)
func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
	if ptr, ok := data.(unsafe.Pointer); ok {
		return internal.NewPointer(ptr), nil
	}
	buf, err := marshalBytes(data, length)
	if err != nil {
		return internal.Pointer{}, err
	}
	return internal.NewSlicePointer(buf), nil
}
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
	switch value := data.(type) {
	case encoding.BinaryMarshaler:
		buf, err = value.MarshalBinary()
	case string:
		buf = []byte(value)
	case []byte:
		buf = value
	case unsafe.Pointer:
		err = errors.New("can't marshal from unsafe.Pointer")
	case Map, *Map, Program, *Program:
		err = fmt.Errorf("can't marshal %T", value)
	default:
		var wr bytes.Buffer
		err = binary.Write(&wr, internal.NativeEndian, value)
		if err != nil {
			err = fmt.Errorf("encoding %T: %v", value, err)
		}
		buf = wr.Bytes()
	}
	if err != nil {
		return nil, err
	}
	if len(buf) != length {
		return nil, fmt.Errorf("%T doesn't marshal to %d bytes", data, length)
	}
	return buf, nil
}
func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) {
	if ptr, ok := dst.(unsafe.Pointer); ok {
		return internal.NewPointer(ptr), nil
	}
	buf := make([]byte, length)
	return internal.NewSlicePointer(buf), buf
}