github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/btfhelpers/btfhelpers.go (about)

     1  // Copyright 2024 The Inspektor Gadget authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package btfhelpers provides a couple of helper functions to bridge Go's reflection system with
    16  // types from BTF
    17  package btfhelpers
    18  
    19  import (
    20  	"reflect"
    21  
    22  	"github.com/cilium/ebpf/btf"
    23  )
    24  
    25  // GetType returns the reflect.Type for a given BTF type and the list of type names found while
    26  // resolving it.
    27  func GetType(typ btf.Type) (reflect.Type, []string) {
    28  	var refType reflect.Type
    29  	typeNames := []string{}
    30  
    31  	if typ.TypeName() != "" {
    32  		typeNames = append(typeNames, typ.TypeName())
    33  	}
    34  
    35  	switch typed := typ.(type) {
    36  	case *btf.Array:
    37  		arrType := getSimpleType(typed.Type)
    38  		if arrType == nil {
    39  			return nil, nil
    40  		}
    41  		if typed.Type.TypeName() != "" {
    42  			typeNames = append(typeNames, typed.Type.TypeName())
    43  		}
    44  		refType = reflect.ArrayOf(int(typed.Nelems), arrType)
    45  	case *btf.Typedef:
    46  		switch typed := typ.(type) {
    47  		case *btf.Typedef:
    48  			refType, typeNames2 := GetType(typed.Type)
    49  			typeNames = append(typeNames, typeNames2...)
    50  			return refType, typeNames
    51  		default:
    52  			return GetType(typed)
    53  		}
    54  	default:
    55  		refType = getSimpleType(typ)
    56  	}
    57  
    58  	return refType, typeNames
    59  }
    60  
    61  // GetUnderlyingType returns the underlying type of a typedef
    62  func GetUnderlyingType(tf *btf.Typedef) btf.Type {
    63  	switch typed := tf.Type.(type) {
    64  	case *btf.Typedef:
    65  		return GetUnderlyingType(typed)
    66  	default:
    67  		return typed
    68  	}
    69  }
    70  
    71  func getSimpleType(typ btf.Type) reflect.Type {
    72  	switch typed := typ.(type) {
    73  	case *btf.Int:
    74  		switch typed.Encoding {
    75  		case btf.Signed:
    76  			switch typed.Size {
    77  			case 1:
    78  				return reflect.TypeOf(int8(0))
    79  			case 2:
    80  				return reflect.TypeOf(int16(0))
    81  			case 4:
    82  				return reflect.TypeOf(int32(0))
    83  			case 8:
    84  				return reflect.TypeOf(int64(0))
    85  			}
    86  		case btf.Unsigned:
    87  			switch typed.Size {
    88  			case 1:
    89  				return reflect.TypeOf(uint8(0))
    90  			case 2:
    91  				return reflect.TypeOf(uint16(0))
    92  			case 4:
    93  				return reflect.TypeOf(uint32(0))
    94  			case 8:
    95  				return reflect.TypeOf(uint64(0))
    96  			}
    97  		case btf.Bool:
    98  			return reflect.TypeOf(false)
    99  		case btf.Char:
   100  			return reflect.TypeOf(uint8(0))
   101  		}
   102  	case *btf.Float:
   103  		switch typed.Size {
   104  		case 4:
   105  			return reflect.TypeOf(float32(0))
   106  		case 8:
   107  			return reflect.TypeOf(float64(0))
   108  		}
   109  	case *btf.Enum:
   110  		if typed.Signed {
   111  			switch typed.Size {
   112  			case 1:
   113  				return reflect.TypeOf(int8(0))
   114  			case 2:
   115  				return reflect.TypeOf(int16(0))
   116  			case 4:
   117  				return reflect.TypeOf(int32(0))
   118  			case 8:
   119  				return reflect.TypeOf(int64(0))
   120  			}
   121  		}
   122  
   123  		switch typed.Size {
   124  		case 1:
   125  			return reflect.TypeOf(uint8(0))
   126  		case 2:
   127  			return reflect.TypeOf(uint16(0))
   128  		case 4:
   129  			return reflect.TypeOf(uint32(0))
   130  		case 8:
   131  			return reflect.TypeOf(uint64(0))
   132  		}
   133  	}
   134  	return nil
   135  }