github.com/cilium/ebpf@v0.10.0/btf/btf_types.go (about)

     1  package btf
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"io"
     7  )
     8  
     9  //go:generate stringer -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage,btfKind
    10  
    11  // btfKind describes a Type.
    12  type btfKind uint8
    13  
    14  // Equivalents of the BTF_KIND_* constants.
    15  const (
    16  	kindUnknown  btfKind = iota // Unknown
    17  	kindInt                     // Int
    18  	kindPointer                 // Pointer
    19  	kindArray                   // Array
    20  	kindStruct                  // Struct
    21  	kindUnion                   // Union
    22  	kindEnum                    // Enum
    23  	kindForward                 // Forward
    24  	kindTypedef                 // Typedef
    25  	kindVolatile                // Volatile
    26  	kindConst                   // Const
    27  	kindRestrict                // Restrict
    28  	// Added ~4.20
    29  	kindFunc      // Func
    30  	kindFuncProto // FuncProto
    31  	// Added ~5.1
    32  	kindVar     // Var
    33  	kindDatasec // Datasec
    34  	// Added ~5.13
    35  	kindFloat // Float
    36  	// Added 5.16
    37  	kindDeclTag // DeclTag
    38  	kindTypeTag // TypeTag
    39  	// Added 6.0
    40  	kindEnum64 // Enum64
    41  )
    42  
    43  // FuncLinkage describes BTF function linkage metadata.
    44  type FuncLinkage int
    45  
    46  // Equivalent of enum btf_func_linkage.
    47  const (
    48  	StaticFunc FuncLinkage = iota // static
    49  	GlobalFunc                    // global
    50  	ExternFunc                    // extern
    51  )
    52  
    53  // VarLinkage describes BTF variable linkage metadata.
    54  type VarLinkage int
    55  
    56  const (
    57  	StaticVar VarLinkage = iota // static
    58  	GlobalVar                   // global
    59  	ExternVar                   // extern
    60  )
    61  
    62  const (
    63  	btfTypeKindShift     = 24
    64  	btfTypeKindLen       = 5
    65  	btfTypeVlenShift     = 0
    66  	btfTypeVlenMask      = 16
    67  	btfTypeKindFlagShift = 31
    68  	btfTypeKindFlagMask  = 1
    69  )
    70  
    71  var btfTypeLen = binary.Size(btfType{})
    72  
    73  // btfType is equivalent to struct btf_type in Documentation/bpf/btf.rst.
    74  type btfType struct {
    75  	NameOff uint32
    76  	/* "info" bits arrangement
    77  	 * bits  0-15: vlen (e.g. # of struct's members), linkage
    78  	 * bits 16-23: unused
    79  	 * bits 24-28: kind (e.g. int, ptr, array...etc)
    80  	 * bits 29-30: unused
    81  	 * bit     31: kind_flag, currently used by
    82  	 *             struct, union and fwd
    83  	 */
    84  	Info uint32
    85  	/* "size" is used by INT, ENUM, STRUCT and UNION.
    86  	 * "size" tells the size of the type it is describing.
    87  	 *
    88  	 * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
    89  	 * FUNC and FUNC_PROTO.
    90  	 * "type" is a type_id referring to another type.
    91  	 */
    92  	SizeType uint32
    93  }
    94  
    95  func mask(len uint32) uint32 {
    96  	return (1 << len) - 1
    97  }
    98  
    99  func readBits(value, len, shift uint32) uint32 {
   100  	return (value >> shift) & mask(len)
   101  }
   102  
   103  func writeBits(value, len, shift, new uint32) uint32 {
   104  	value &^= mask(len) << shift
   105  	value |= (new & mask(len)) << shift
   106  	return value
   107  }
   108  
   109  func (bt *btfType) info(len, shift uint32) uint32 {
   110  	return readBits(bt.Info, len, shift)
   111  }
   112  
   113  func (bt *btfType) setInfo(value, len, shift uint32) {
   114  	bt.Info = writeBits(bt.Info, len, shift, value)
   115  }
   116  
   117  func (bt *btfType) Kind() btfKind {
   118  	return btfKind(bt.info(btfTypeKindLen, btfTypeKindShift))
   119  }
   120  
   121  func (bt *btfType) SetKind(kind btfKind) {
   122  	bt.setInfo(uint32(kind), btfTypeKindLen, btfTypeKindShift)
   123  }
   124  
   125  func (bt *btfType) Vlen() int {
   126  	return int(bt.info(btfTypeVlenMask, btfTypeVlenShift))
   127  }
   128  
   129  func (bt *btfType) SetVlen(vlen int) {
   130  	bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift)
   131  }
   132  
   133  func (bt *btfType) kindFlagBool() bool {
   134  	return bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift) == 1
   135  }
   136  
   137  func (bt *btfType) setKindFlagBool(set bool) {
   138  	var value uint32
   139  	if set {
   140  		value = 1
   141  	}
   142  	bt.setInfo(value, btfTypeKindFlagMask, btfTypeKindFlagShift)
   143  }
   144  
   145  // Bitfield returns true if the struct or union contain a bitfield.
   146  func (bt *btfType) Bitfield() bool {
   147  	return bt.kindFlagBool()
   148  }
   149  
   150  func (bt *btfType) SetBitfield(isBitfield bool) {
   151  	bt.setKindFlagBool(isBitfield)
   152  }
   153  
   154  func (bt *btfType) FwdKind() FwdKind {
   155  	return FwdKind(bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift))
   156  }
   157  
   158  func (bt *btfType) SetFwdKind(kind FwdKind) {
   159  	bt.setInfo(uint32(kind), btfTypeKindFlagMask, btfTypeKindFlagShift)
   160  }
   161  
   162  func (bt *btfType) Signed() bool {
   163  	return bt.kindFlagBool()
   164  }
   165  
   166  func (bt *btfType) SetSigned(signed bool) {
   167  	bt.setKindFlagBool(signed)
   168  }
   169  
   170  func (bt *btfType) Linkage() FuncLinkage {
   171  	return FuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift))
   172  }
   173  
   174  func (bt *btfType) SetLinkage(linkage FuncLinkage) {
   175  	bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift)
   176  }
   177  
   178  func (bt *btfType) Type() TypeID {
   179  	// TODO: Panic here if wrong kind?
   180  	return TypeID(bt.SizeType)
   181  }
   182  
   183  func (bt *btfType) SetType(id TypeID) {
   184  	bt.SizeType = uint32(id)
   185  }
   186  
   187  func (bt *btfType) Size() uint32 {
   188  	// TODO: Panic here if wrong kind?
   189  	return bt.SizeType
   190  }
   191  
   192  func (bt *btfType) SetSize(size uint32) {
   193  	bt.SizeType = size
   194  }
   195  
   196  type rawType struct {
   197  	btfType
   198  	data interface{}
   199  }
   200  
   201  func (rt *rawType) Marshal(w io.Writer, bo binary.ByteOrder) error {
   202  	if err := binary.Write(w, bo, &rt.btfType); err != nil {
   203  		return err
   204  	}
   205  
   206  	if rt.data == nil {
   207  		return nil
   208  	}
   209  
   210  	return binary.Write(w, bo, rt.data)
   211  }
   212  
   213  // btfInt encodes additional data for integers.
   214  //
   215  //	? ? ? ? e e e e o o o o o o o o ? ? ? ? ? ? ? ? b b b b b b b b
   216  //	? = undefined
   217  //	e = encoding
   218  //	o = offset (bitfields?)
   219  //	b = bits (bitfields)
   220  type btfInt struct {
   221  	Raw uint32
   222  }
   223  
   224  const (
   225  	btfIntEncodingLen   = 4
   226  	btfIntEncodingShift = 24
   227  	btfIntOffsetLen     = 8
   228  	btfIntOffsetShift   = 16
   229  	btfIntBitsLen       = 8
   230  	btfIntBitsShift     = 0
   231  )
   232  
   233  func (bi btfInt) Encoding() IntEncoding {
   234  	return IntEncoding(readBits(bi.Raw, btfIntEncodingLen, btfIntEncodingShift))
   235  }
   236  
   237  func (bi *btfInt) SetEncoding(e IntEncoding) {
   238  	bi.Raw = writeBits(uint32(bi.Raw), btfIntEncodingLen, btfIntEncodingShift, uint32(e))
   239  }
   240  
   241  func (bi btfInt) Offset() Bits {
   242  	return Bits(readBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift))
   243  }
   244  
   245  func (bi *btfInt) SetOffset(offset uint32) {
   246  	bi.Raw = writeBits(bi.Raw, btfIntOffsetLen, btfIntOffsetShift, offset)
   247  }
   248  
   249  func (bi btfInt) Bits() Bits {
   250  	return Bits(readBits(bi.Raw, btfIntBitsLen, btfIntBitsShift))
   251  }
   252  
   253  func (bi *btfInt) SetBits(bits byte) {
   254  	bi.Raw = writeBits(bi.Raw, btfIntBitsLen, btfIntBitsShift, uint32(bits))
   255  }
   256  
   257  type btfArray struct {
   258  	Type      TypeID
   259  	IndexType TypeID
   260  	Nelems    uint32
   261  }
   262  
   263  type btfMember struct {
   264  	NameOff uint32
   265  	Type    TypeID
   266  	Offset  uint32
   267  }
   268  
   269  type btfVarSecinfo struct {
   270  	Type   TypeID
   271  	Offset uint32
   272  	Size   uint32
   273  }
   274  
   275  type btfVariable struct {
   276  	Linkage uint32
   277  }
   278  
   279  type btfEnum struct {
   280  	NameOff uint32
   281  	Val     uint32
   282  }
   283  
   284  type btfEnum64 struct {
   285  	NameOff uint32
   286  	ValLo32 uint32
   287  	ValHi32 uint32
   288  }
   289  
   290  type btfParam struct {
   291  	NameOff uint32
   292  	Type    TypeID
   293  }
   294  
   295  type btfDeclTag struct {
   296  	ComponentIdx uint32
   297  }
   298  
   299  func readTypes(r io.Reader, bo binary.ByteOrder, typeLen uint32) ([]rawType, error) {
   300  	var header btfType
   301  	// because of the interleaving between types and struct members it is difficult to
   302  	// precompute the numbers of raw types this will parse
   303  	// this "guess" is a good first estimation
   304  	sizeOfbtfType := uintptr(btfTypeLen)
   305  	tyMaxCount := uintptr(typeLen) / sizeOfbtfType / 2
   306  	types := make([]rawType, 0, tyMaxCount)
   307  
   308  	for id := TypeID(1); ; id++ {
   309  		if err := binary.Read(r, bo, &header); err == io.EOF {
   310  			return types, nil
   311  		} else if err != nil {
   312  			return nil, fmt.Errorf("can't read type info for id %v: %v", id, err)
   313  		}
   314  
   315  		var data interface{}
   316  		switch header.Kind() {
   317  		case kindInt:
   318  			data = new(btfInt)
   319  		case kindPointer:
   320  		case kindArray:
   321  			data = new(btfArray)
   322  		case kindStruct:
   323  			fallthrough
   324  		case kindUnion:
   325  			data = make([]btfMember, header.Vlen())
   326  		case kindEnum:
   327  			data = make([]btfEnum, header.Vlen())
   328  		case kindForward:
   329  		case kindTypedef:
   330  		case kindVolatile:
   331  		case kindConst:
   332  		case kindRestrict:
   333  		case kindFunc:
   334  		case kindFuncProto:
   335  			data = make([]btfParam, header.Vlen())
   336  		case kindVar:
   337  			data = new(btfVariable)
   338  		case kindDatasec:
   339  			data = make([]btfVarSecinfo, header.Vlen())
   340  		case kindFloat:
   341  		case kindDeclTag:
   342  			data = new(btfDeclTag)
   343  		case kindTypeTag:
   344  		case kindEnum64:
   345  			data = make([]btfEnum64, header.Vlen())
   346  		default:
   347  			return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
   348  		}
   349  
   350  		if data == nil {
   351  			types = append(types, rawType{header, nil})
   352  			continue
   353  		}
   354  
   355  		if err := binary.Read(r, bo, data); err != nil {
   356  			return nil, fmt.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err)
   357  		}
   358  
   359  		types = append(types, rawType{header, data})
   360  	}
   361  }