marshalers.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package ebpf
  2. import (
  3. "bytes"
  4. "encoding"
  5. "encoding/binary"
  6. "errors"
  7. "fmt"
  8. "reflect"
  9. "runtime"
  10. "sync"
  11. "unsafe"
  12. "github.com/cilium/ebpf/internal"
  13. "github.com/cilium/ebpf/internal/sys"
  14. )
  15. // marshalPtr converts an arbitrary value into a pointer suitable
  16. // to be passed to the kernel.
  17. //
  18. // As an optimization, it returns the original value if it is an
  19. // unsafe.Pointer.
  20. func marshalPtr(data interface{}, length int) (sys.Pointer, error) {
  21. if ptr, ok := data.(unsafe.Pointer); ok {
  22. return sys.NewPointer(ptr), nil
  23. }
  24. buf, err := marshalBytes(data, length)
  25. if err != nil {
  26. return sys.Pointer{}, err
  27. }
  28. return sys.NewSlicePointer(buf), nil
  29. }
  30. // marshalBytes converts an arbitrary value into a byte buffer.
  31. //
  32. // Prefer using Map.marshalKey and Map.marshalValue if possible, since
  33. // those have special cases that allow more types to be encoded.
  34. //
  35. // Returns an error if the given value isn't representable in exactly
  36. // length bytes.
  37. func marshalBytes(data interface{}, length int) (buf []byte, err error) {
  38. if data == nil {
  39. return nil, errors.New("can't marshal a nil value")
  40. }
  41. switch value := data.(type) {
  42. case encoding.BinaryMarshaler:
  43. buf, err = value.MarshalBinary()
  44. case string:
  45. buf = []byte(value)
  46. case []byte:
  47. buf = value
  48. case unsafe.Pointer:
  49. err = errors.New("can't marshal from unsafe.Pointer")
  50. case Map, *Map, Program, *Program:
  51. err = fmt.Errorf("can't marshal %T", value)
  52. default:
  53. var wr bytes.Buffer
  54. err = binary.Write(&wr, internal.NativeEndian, value)
  55. if err != nil {
  56. err = fmt.Errorf("encoding %T: %v", value, err)
  57. }
  58. buf = wr.Bytes()
  59. }
  60. if err != nil {
  61. return nil, err
  62. }
  63. if len(buf) != length {
  64. return nil, fmt.Errorf("%T doesn't marshal to %d bytes", data, length)
  65. }
  66. return buf, nil
  67. }
  68. func makeBuffer(dst interface{}, length int) (sys.Pointer, []byte) {
  69. if ptr, ok := dst.(unsafe.Pointer); ok {
  70. return sys.NewPointer(ptr), nil
  71. }
  72. buf := make([]byte, length)
  73. return sys.NewSlicePointer(buf), buf
  74. }
  75. var bytesReaderPool = sync.Pool{
  76. New: func() interface{} {
  77. return new(bytes.Reader)
  78. },
  79. }
  80. // unmarshalBytes converts a byte buffer into an arbitrary value.
  81. //
  82. // Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
  83. // those have special cases that allow more types to be encoded.
  84. //
  85. // The common int32 and int64 types are directly handled to avoid
  86. // unnecessary heap allocations as happening in the default case.
  87. func unmarshalBytes(data interface{}, buf []byte) error {
  88. switch value := data.(type) {
  89. case unsafe.Pointer:
  90. dst := unsafe.Slice((*byte)(value), len(buf))
  91. copy(dst, buf)
  92. runtime.KeepAlive(value)
  93. return nil
  94. case Map, *Map, Program, *Program:
  95. return fmt.Errorf("can't unmarshal into %T", value)
  96. case encoding.BinaryUnmarshaler:
  97. return value.UnmarshalBinary(buf)
  98. case *string:
  99. *value = string(buf)
  100. return nil
  101. case *[]byte:
  102. *value = buf
  103. return nil
  104. case *int32:
  105. if len(buf) < 4 {
  106. return errors.New("int32 requires 4 bytes")
  107. }
  108. *value = int32(internal.NativeEndian.Uint32(buf))
  109. return nil
  110. case *uint32:
  111. if len(buf) < 4 {
  112. return errors.New("uint32 requires 4 bytes")
  113. }
  114. *value = internal.NativeEndian.Uint32(buf)
  115. return nil
  116. case *int64:
  117. if len(buf) < 8 {
  118. return errors.New("int64 requires 8 bytes")
  119. }
  120. *value = int64(internal.NativeEndian.Uint64(buf))
  121. return nil
  122. case *uint64:
  123. if len(buf) < 8 {
  124. return errors.New("uint64 requires 8 bytes")
  125. }
  126. *value = internal.NativeEndian.Uint64(buf)
  127. return nil
  128. case string:
  129. return errors.New("require pointer to string")
  130. case []byte:
  131. return errors.New("require pointer to []byte")
  132. default:
  133. rd := bytesReaderPool.Get().(*bytes.Reader)
  134. rd.Reset(buf)
  135. defer bytesReaderPool.Put(rd)
  136. if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
  137. return fmt.Errorf("decoding %T: %v", value, err)
  138. }
  139. return nil
  140. }
  141. }
  142. // marshalPerCPUValue encodes a slice containing one value per
  143. // possible CPU into a buffer of bytes.
  144. //
  145. // Values are initialized to zero if the slice has less elements than CPUs.
  146. //
  147. // slice must have a type like []elementType.
  148. func marshalPerCPUValue(slice interface{}, elemLength int) (sys.Pointer, error) {
  149. sliceType := reflect.TypeOf(slice)
  150. if sliceType.Kind() != reflect.Slice {
  151. return sys.Pointer{}, errors.New("per-CPU value requires slice")
  152. }
  153. possibleCPUs, err := internal.PossibleCPUs()
  154. if err != nil {
  155. return sys.Pointer{}, err
  156. }
  157. sliceValue := reflect.ValueOf(slice)
  158. sliceLen := sliceValue.Len()
  159. if sliceLen > possibleCPUs {
  160. return sys.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
  161. }
  162. alignedElemLength := internal.Align(elemLength, 8)
  163. buf := make([]byte, alignedElemLength*possibleCPUs)
  164. for i := 0; i < sliceLen; i++ {
  165. elem := sliceValue.Index(i).Interface()
  166. elemBytes, err := marshalBytes(elem, elemLength)
  167. if err != nil {
  168. return sys.Pointer{}, err
  169. }
  170. offset := i * alignedElemLength
  171. copy(buf[offset:offset+elemLength], elemBytes)
  172. }
  173. return sys.NewSlicePointer(buf), nil
  174. }
  175. // unmarshalPerCPUValue decodes a buffer into a slice containing one value per
  176. // possible CPU.
  177. //
  178. // valueOut must have a type like *[]elementType
  179. func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) error {
  180. slicePtrType := reflect.TypeOf(slicePtr)
  181. if slicePtrType.Kind() != reflect.Ptr || slicePtrType.Elem().Kind() != reflect.Slice {
  182. return fmt.Errorf("per-cpu value requires pointer to slice")
  183. }
  184. possibleCPUs, err := internal.PossibleCPUs()
  185. if err != nil {
  186. return err
  187. }
  188. sliceType := slicePtrType.Elem()
  189. slice := reflect.MakeSlice(sliceType, possibleCPUs, possibleCPUs)
  190. sliceElemType := sliceType.Elem()
  191. sliceElemIsPointer := sliceElemType.Kind() == reflect.Ptr
  192. if sliceElemIsPointer {
  193. sliceElemType = sliceElemType.Elem()
  194. }
  195. step := len(buf) / possibleCPUs
  196. if step < elemLength {
  197. return fmt.Errorf("per-cpu element length is larger than available data")
  198. }
  199. for i := 0; i < possibleCPUs; i++ {
  200. var elem interface{}
  201. if sliceElemIsPointer {
  202. newElem := reflect.New(sliceElemType)
  203. slice.Index(i).Set(newElem)
  204. elem = newElem.Interface()
  205. } else {
  206. elem = slice.Index(i).Addr().Interface()
  207. }
  208. // Make a copy, since unmarshal can hold on to itemBytes
  209. elemBytes := make([]byte, elemLength)
  210. copy(elemBytes, buf[:elemLength])
  211. err := unmarshalBytes(elem, elemBytes)
  212. if err != nil {
  213. return fmt.Errorf("cpu %d: %w", i, err)
  214. }
  215. buf = buf[step:]
  216. }
  217. reflect.ValueOf(slicePtr).Elem().Set(slice)
  218. return nil
  219. }