github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/btf/btf_types.go (about)

     1  package btf
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"unsafe"
     9  
    10  	"github.com/cilium/ebpf/internal"
    11  )
    12  
    13  //go:generate go run golang.org/x/tools/cmd/stringer@latest -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage,btfKind
    14  
    15  // btfKind describes a Type.
    16  type btfKind uint8
    17  
    18  // Equivalents of the BTF_KIND_* constants.
    19  const (
    20  	kindUnknown  btfKind = iota // Unknown
    21  	kindInt                     // Int
    22  	kindPointer                 // Pointer
    23  	kindArray                   // Array
    24  	kindStruct                  // Struct
    25  	kindUnion                   // Union
    26  	kindEnum                    // Enum
    27  	kindForward                 // Forward
    28  	kindTypedef                 // Typedef
    29  	kindVolatile                // Volatile
    30  	kindConst                   // Const
    31  	kindRestrict                // Restrict
    32  	// Added ~4.20
    33  	kindFunc      // Func
    34  	kindFuncProto // FuncProto
    35  	// Added ~5.1
    36  	kindVar     // Var
    37  	kindDatasec // Datasec
    38  	// Added ~5.13
    39  	kindFloat // Float
    40  	// Added 5.16
    41  	kindDeclTag // DeclTag
    42  	kindTypeTag // TypeTag
    43  	// Added 6.0
    44  	kindEnum64 // Enum64
    45  )
    46  
    47  // FuncLinkage describes BTF function linkage metadata.
    48  type FuncLinkage int
    49  
    50  // Equivalent of enum btf_func_linkage.
    51  const (
    52  	StaticFunc FuncLinkage = iota // static
    53  	GlobalFunc                    // global
    54  	ExternFunc                    // extern
    55  )
    56  
    57  // VarLinkage describes BTF variable linkage metadata.
    58  type VarLinkage int
    59  
    60  const (
    61  	StaticVar VarLinkage = iota // static
    62  	GlobalVar                   // global
    63  	ExternVar                   // extern
    64  )
    65  
    66  const (
    67  	btfTypeKindShift     = 24
    68  	btfTypeKindLen       = 5
    69  	btfTypeVlenShift     = 0
    70  	btfTypeVlenMask      = 16
    71  	btfTypeKindFlagShift = 31
    72  	btfTypeKindFlagMask  = 1
    73  )
    74  
    75  var btfHeaderLen = binary.Size(&btfHeader{})
    76  
    77  type btfHeader struct {
    78  	Magic   uint16
    79  	Version uint8
    80  	Flags   uint8
    81  	HdrLen  uint32
    82  
    83  	TypeOff   uint32
    84  	TypeLen   uint32
    85  	StringOff uint32
    86  	StringLen uint32
    87  }
    88  
    89  // typeStart returns the offset from the beginning of the .BTF section
    90  // to the start of its type entries.
    91  func (h *btfHeader) typeStart() int64 {
    92  	return int64(h.HdrLen + h.TypeOff)
    93  }
    94  
    95  // stringStart returns the offset from the beginning of the .BTF section
    96  // to the start of its string table.
    97  func (h *btfHeader) stringStart() int64 {
    98  	return int64(h.HdrLen + h.StringOff)
    99  }
   100  
   101  // parseBTFHeader parses the header of the .BTF section.
   102  func parseBTFHeader(r io.Reader, bo binary.ByteOrder) (*btfHeader, error) {
   103  	var header btfHeader
   104  	if err := binary.Read(r, bo, &header); err != nil {
   105  		return nil, fmt.Errorf("can't read header: %v", err)
   106  	}
   107  
   108  	if header.Magic != btfMagic {
   109  		return nil, fmt.Errorf("incorrect magic value %v", header.Magic)
   110  	}
   111  
   112  	if header.Version != 1 {
   113  		return nil, fmt.Errorf("unexpected version %v", header.Version)
   114  	}
   115  
   116  	if header.Flags != 0 {
   117  		return nil, fmt.Errorf("unsupported flags %v", header.Flags)
   118  	}
   119  
   120  	remainder := int64(header.HdrLen) - int64(binary.Size(&header))
   121  	if remainder < 0 {
   122  		return nil, errors.New("header length shorter than btfHeader size")
   123  	}
   124  
   125  	if _, err := io.CopyN(internal.DiscardZeroes{}, r, remainder); err != nil {
   126  		return nil, fmt.Errorf("header padding: %v", err)
   127  	}
   128  
   129  	return &header, nil
   130  }
   131  
   132  var btfTypeLen = binary.Size(btfType{})
   133  
   134  // btfType is equivalent to struct btf_type in Documentation/bpf/btf.rst.
   135  type btfType struct {
   136  	NameOff uint32
   137  	/* "info" bits arrangement
   138  	 * bits  0-15: vlen (e.g. # of struct's members), linkage
   139  	 * bits 16-23: unused
   140  	 * bits 24-28: kind (e.g. int, ptr, array...etc)
   141  	 * bits 29-30: unused
   142  	 * bit     31: kind_flag, currently used by
   143  	 *             struct, union and fwd
   144  	 */
   145  	Info uint32
   146  	/* "size" is used by INT, ENUM, STRUCT and UNION.
   147  	 * "size" tells the size of the type it is describing.
   148  	 *
   149  	 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
   150  	 * FUNC and FUNC_PROTO.
   151  	 * "type" is a type_id referring to another type.
   152  	 */
   153  	SizeType uint32
   154  }
   155  
   156  var btfTypeSize = int(unsafe.Sizeof(btfType{}))
   157  
   158  func unmarshalBtfType(bt *btfType, b []byte, bo binary.ByteOrder) (int, error) {
   159  	if len(b) < btfTypeSize {
   160  		return 0, fmt.Errorf("not enough bytes to unmarshal btfType")
   161  	}
   162  
   163  	bt.NameOff = bo.Uint32(b[0:])
   164  	bt.Info = bo.Uint32(b[4:])
   165  	bt.SizeType = bo.Uint32(b[8:])
   166  	return btfTypeSize, nil
   167  }
   168  
   169  func mask(len uint32) uint32 {
   170  	return (1 << len) - 1
   171  }
   172  
   173  func readBits(value, len, shift uint32) uint32 {
   174  	return (value >> shift) & mask(len)
   175  }
   176  
   177  func writeBits(value, len, shift, new uint32) uint32 {
   178  	value &^= mask(len) << shift
   179  	value |= (new & mask(len)) << shift
   180  	return value
   181  }
   182  
   183  func (bt *btfType) info(len, shift uint32) uint32 {
   184  	return readBits(bt.Info, len, shift)
   185  }
   186  
   187  func (bt *btfType) setInfo(value, len, shift uint32) {
   188  	bt.Info = writeBits(bt.Info, len, shift, value)
   189  }
   190  
   191  func (bt *btfType) Kind() btfKind {
   192  	return btfKind(bt.info(btfTypeKindLen, btfTypeKindShift))
   193  }
   194  
   195  func (bt *btfType) SetKind(kind btfKind) {
   196  	bt.setInfo(uint32(kind), btfTypeKindLen, btfTypeKindShift)
   197  }
   198  
   199  func (bt *btfType) Vlen() int {
   200  	return int(bt.info(btfTypeVlenMask, btfTypeVlenShift))
   201  }
   202  
   203  func (bt *btfType) SetVlen(vlen int) {
   204  	bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift)
   205  }
   206  
   207  func (bt *btfType) kindFlagBool() bool {
   208  	return bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift) == 1
   209  }
   210  
   211  func (bt *btfType) setKindFlagBool(set bool) {
   212  	var value uint32
   213  	if set {
   214  		value = 1
   215  	}
   216  	bt.setInfo(value, btfTypeKindFlagMask, btfTypeKindFlagShift)
   217  }
   218  
   219  // Bitfield returns true if the struct or union contain a bitfield.
   220  func (bt *btfType) Bitfield() bool {
   221  	return bt.kindFlagBool()
   222  }
   223  
   224  func (bt *btfType) SetBitfield(isBitfield bool) {
   225  	bt.setKindFlagBool(isBitfield)
   226  }
   227  
   228  func (bt *btfType) FwdKind() FwdKind {
   229  	return FwdKind(bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift))
   230  }
   231  
   232  func (bt *btfType) SetFwdKind(kind FwdKind) {
   233  	bt.setInfo(uint32(kind), btfTypeKindFlagMask, btfTypeKindFlagShift)
   234  }
   235  
   236  func (bt *btfType) Signed() bool {
   237  	return bt.kindFlagBool()
   238  }
   239  
   240  func (bt *btfType) SetSigned(signed bool) {
   241  	bt.setKindFlagBool(signed)
   242  }
   243  
   244  func (bt *btfType) Linkage() FuncLinkage {
   245  	return FuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift))
   246  }
   247  
   248  func (bt *btfType) SetLinkage(linkage FuncLinkage) {
   249  	bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift)
   250  }
   251  
   252  func (bt *btfType) Type() TypeID {
   253  	// TODO: Panic here if wrong kind?
   254  	return TypeID(bt.SizeType)
   255  }
   256  
   257  func (bt *btfType) SetType(id TypeID) {
   258  	bt.SizeType = uint32(id)
   259  }
   260  
   261  func (bt *btfType) Size() uint32 {
   262  	// TODO: Panic here if wrong kind?
   263  	return bt.SizeType
   264  }
   265  
   266  func (bt *btfType) SetSize(size uint32) {
   267  	bt.SizeType = size
   268  }
   269  
   270  func (bt *btfType) Marshal(w io.Writer, bo binary.ByteOrder) error {
   271  	buf := make([]byte, unsafe.Sizeof(*bt))
   272  	bo.PutUint32(buf[0:], bt.NameOff)
   273  	bo.PutUint32(buf[4:], bt.Info)
   274  	bo.PutUint32(buf[8:], bt.SizeType)
   275  	_, err := w.Write(buf)
   276  	return err
   277  }
   278  
   279  type rawType struct {
   280  	btfType
   281  	data interface{}
   282  }
   283  
   284  func (rt *rawType) Marshal(w io.Writer, bo binary.ByteOrder) error {
   285  	if err := rt.btfType.Marshal(w, bo); err != nil {
   286  		return err
   287  	}
   288  
   289  	if rt.data == nil {
   290  		return nil
   291  	}
   292  
   293  	return binary.Write(w, bo, rt.data)
   294  }
   295  
   296  // btfInt encodes additional data for integers.
   297  //
   298  //	? ? ? ? e e e e o o o o o o o o ? ? ? ? ? ? ? ? b b b b b b b b
   299  //	? = undefined
   300  //	e = encoding
   301  //	o = offset (bitfields?)
   302  //	b = bits (bitfields)
   303  type btfInt struct {
   304  	Raw uint32
   305  }
   306  
   307  const (
   308  	btfIntEncodingLen   = 4
   309  	btfIntEncodingShift = 24
   310  	btfIntOffsetLen     = 8
   311  	btfIntOffsetShift   = 16
   312  	btfIntBitsLen       = 8
   313  	btfIntBitsShift     = 0
   314  )
   315  
   316  var btfIntLen = int(unsafe.Sizeof(btfInt{}))
   317  
   318  func unmarshalBtfInt(bi *btfInt, b []byte, bo binary.ByteOrder) (int, error) {
   319  	if len(b) < btfIntLen {
   320  		return 0, fmt.Errorf("not enough bytes to unmarshal btfInt")
   321  	}
   322  
   323  	bi.Raw = bo.Uint32(b[0:])
   324  	return btfIntLen, nil
   325  }
   326  
   327  func (bi btfInt) Encoding() IntEncoding {
   328  	return IntEncoding(readBits(bi.Raw, btfIntEncodingLen, btfIntEncodingShift))
   329  }
   330  
   331  func (bi *btfInt) SetEncoding(e IntEncoding) {
   332  	bi.Raw = writeBits(uint32(bi.Raw), btfIntEncodingLen, btfIntEncodingShift, uint32(e))
   333  }
   334  
   335  func (bi btfInt) Offset() Bits {
   336  	return Bits(readBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift))
   337  }
   338  
   339  func (bi *btfInt) SetOffset(offset uint32) {
   340  	bi.Raw = writeBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift, offset)
   341  }
   342  
   343  func (bi btfInt) Bits() Bits {
   344  	return Bits(readBits(bi.Raw, btfIntBitsLen, btfIntBitsShift))
   345  }
   346  
   347  func (bi *btfInt) SetBits(bits byte) {
   348  	bi.Raw = writeBits(bi.Raw, btfIntBitsLen, btfIntBitsShift, uint32(bits))
   349  }
   350  
   351  type btfArray struct {
   352  	Type      TypeID
   353  	IndexType TypeID
   354  	Nelems    uint32
   355  }
   356  
   357  var btfArrayLen = int(unsafe.Sizeof(btfArray{}))
   358  
   359  func unmarshalBtfArray(ba *btfArray, b []byte, bo binary.ByteOrder) (int, error) {
   360  	if len(b) < btfArrayLen {
   361  		return 0, fmt.Errorf("not enough bytes to unmarshal btfArray")
   362  	}
   363  
   364  	ba.Type = TypeID(bo.Uint32(b[0:]))
   365  	ba.IndexType = TypeID(bo.Uint32(b[4:]))
   366  	ba.Nelems = bo.Uint32(b[8:])
   367  	return btfArrayLen, nil
   368  }
   369  
   370  type btfMember struct {
   371  	NameOff uint32
   372  	Type    TypeID
   373  	Offset  uint32
   374  }
   375  
   376  var btfMemberLen = int(unsafe.Sizeof(btfMember{}))
   377  
   378  func unmarshalBtfMembers(members []btfMember, b []byte, bo binary.ByteOrder) (int, error) {
   379  	off := 0
   380  	for i := range members {
   381  		if off+btfMemberLen > len(b) {
   382  			return 0, fmt.Errorf("not enough bytes to unmarshal btfMember %d", i)
   383  		}
   384  
   385  		members[i].NameOff = bo.Uint32(b[off+0:])
   386  		members[i].Type = TypeID(bo.Uint32(b[off+4:]))
   387  		members[i].Offset = bo.Uint32(b[off+8:])
   388  
   389  		off += btfMemberLen
   390  	}
   391  
   392  	return off, nil
   393  }
   394  
   395  type btfVarSecinfo struct {
   396  	Type   TypeID
   397  	Offset uint32
   398  	Size   uint32
   399  }
   400  
   401  var btfVarSecinfoLen = int(unsafe.Sizeof(btfVarSecinfo{}))
   402  
   403  func unmarshalBtfVarSecInfos(secinfos []btfVarSecinfo, b []byte, bo binary.ByteOrder) (int, error) {
   404  	off := 0
   405  	for i := range secinfos {
   406  		if off+btfVarSecinfoLen > len(b) {
   407  			return 0, fmt.Errorf("not enough bytes to unmarshal btfVarSecinfo %d", i)
   408  		}
   409  
   410  		secinfos[i].Type = TypeID(bo.Uint32(b[off+0:]))
   411  		secinfos[i].Offset = bo.Uint32(b[off+4:])
   412  		secinfos[i].Size = bo.Uint32(b[off+8:])
   413  
   414  		off += btfVarSecinfoLen
   415  	}
   416  
   417  	return off, nil
   418  }
   419  
   420  type btfVariable struct {
   421  	Linkage uint32
   422  }
   423  
   424  var btfVariableLen = int(unsafe.Sizeof(btfVariable{}))
   425  
   426  func unmarshalBtfVariable(bv *btfVariable, b []byte, bo binary.ByteOrder) (int, error) {
   427  	if len(b) < btfVariableLen {
   428  		return 0, fmt.Errorf("not enough bytes to unmarshal btfVariable")
   429  	}
   430  
   431  	bv.Linkage = bo.Uint32(b[0:])
   432  	return btfVariableLen, nil
   433  }
   434  
   435  type btfEnum struct {
   436  	NameOff uint32
   437  	Val     uint32
   438  }
   439  
   440  var btfEnumLen = int(unsafe.Sizeof(btfEnum{}))
   441  
   442  func unmarshalBtfEnums(enums []btfEnum, b []byte, bo binary.ByteOrder) (int, error) {
   443  	off := 0
   444  	for i := range enums {
   445  		if off+btfEnumLen > len(b) {
   446  			return 0, fmt.Errorf("not enough bytes to unmarshal btfEnum %d", i)
   447  		}
   448  
   449  		enums[i].NameOff = bo.Uint32(b[off+0:])
   450  		enums[i].Val = bo.Uint32(b[off+4:])
   451  
   452  		off += btfEnumLen
   453  	}
   454  
   455  	return off, nil
   456  }
   457  
   458  type btfEnum64 struct {
   459  	NameOff uint32
   460  	ValLo32 uint32
   461  	ValHi32 uint32
   462  }
   463  
   464  var btfEnum64Len = int(unsafe.Sizeof(btfEnum64{}))
   465  
   466  func unmarshalBtfEnums64(enums []btfEnum64, b []byte, bo binary.ByteOrder) (int, error) {
   467  	off := 0
   468  	for i := range enums {
   469  		if off+btfEnum64Len > len(b) {
   470  			return 0, fmt.Errorf("not enough bytes to unmarshal btfEnum64 %d", i)
   471  		}
   472  
   473  		enums[i].NameOff = bo.Uint32(b[off+0:])
   474  		enums[i].ValLo32 = bo.Uint32(b[off+4:])
   475  		enums[i].ValHi32 = bo.Uint32(b[off+8:])
   476  
   477  		off += btfEnum64Len
   478  	}
   479  
   480  	return off, nil
   481  }
   482  
   483  type btfParam struct {
   484  	NameOff uint32
   485  	Type    TypeID
   486  }
   487  
   488  var btfParamLen = int(unsafe.Sizeof(btfParam{}))
   489  
   490  func unmarshalBtfParams(params []btfParam, b []byte, bo binary.ByteOrder) (int, error) {
   491  	off := 0
   492  	for i := range params {
   493  		if off+btfParamLen > len(b) {
   494  			return 0, fmt.Errorf("not enough bytes to unmarshal btfParam %d", i)
   495  		}
   496  
   497  		params[i].NameOff = bo.Uint32(b[off+0:])
   498  		params[i].Type = TypeID(bo.Uint32(b[off+4:]))
   499  
   500  		off += btfParamLen
   501  	}
   502  
   503  	return off, nil
   504  }
   505  
   506  type btfDeclTag struct {
   507  	ComponentIdx uint32
   508  }
   509  
   510  var btfDeclTagLen = int(unsafe.Sizeof(btfDeclTag{}))
   511  
   512  func unmarshalBtfDeclTag(bdt *btfDeclTag, b []byte, bo binary.ByteOrder) (int, error) {
   513  	if len(b) < btfDeclTagLen {
   514  		return 0, fmt.Errorf("not enough bytes to unmarshal btfDeclTag")
   515  	}
   516  
   517  	bdt.ComponentIdx = bo.Uint32(b[0:])
   518  	return btfDeclTagLen, nil
   519  }