github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/operators/ebpf/params_defaults.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 ebpfoperator 16 17 import ( 18 "errors" 19 "fmt" 20 "strings" 21 "unsafe" 22 23 "github.com/cilium/ebpf" 24 "github.com/cilium/ebpf/btf" 25 26 "github.com/inspektor-gadget/inspektor-gadget/pkg/btfhelpers" 27 ) 28 29 var errMapNoBTFValue = errors.New("map spec does not contain a BTF Value") 30 31 // fillParamDefaults will fill out i.Params' default values 32 func (i *ebpfInstance) fillParamDefaults() error { 33 spec := i.collectionSpec 34 for name, spec := range spec.Maps { 35 if !strings.HasPrefix(name, ".rodata") { 36 continue 37 } 38 b, ds, err := dataSection(spec) 39 if errors.Is(err, errMapNoBTFValue) { 40 continue 41 } 42 if err != nil { 43 return fmt.Errorf("map %s: %w", name, err) 44 } 45 46 for _, v := range ds.Vars { 47 vname := v.Type.TypeName() 48 49 param, ok := i.params[vname] 50 if !ok { 51 continue 52 } 53 54 if int(v.Offset+v.Size) > len(b) { 55 continue 56 } 57 58 btfVar, ok := v.Type.(*btf.Var) 59 if !ok { 60 continue 61 } 62 63 btfConst, ok := btfVar.Type.(*btf.Const) 64 if !ok { 65 continue 66 } 67 68 btfVolatile, ok := btfConst.Type.(*btf.Volatile) 69 if !ok { 70 continue 71 } 72 73 vtype := btfVolatile.Type 74 75 if typedef, ok := vtype.(*btf.Typedef); ok { 76 vtype = btfhelpers.GetUnderlyingType(typedef) 77 } 78 79 bytes := b[v.Offset : v.Offset+v.Size] 80 81 var defaultValue string 82 83 switch t := vtype.(type) { 84 case *btf.Int: 85 if t.Encoding&btf.Signed != 0 { 86 switch t.Size { 87 case 1: 88 defaultValue = fmt.Sprintf("%d", int8(bytes[0])) 89 case 2: 90 defaultValue = fmt.Sprintf("%d", *(*int16)(unsafe.Pointer(&bytes[0]))) 91 case 4: 92 defaultValue = fmt.Sprintf("%d", *(*int32)(unsafe.Pointer(&bytes[0]))) 93 case 8: 94 defaultValue = fmt.Sprintf("%d", *(*int64)(unsafe.Pointer(&bytes[0]))) 95 } 96 } else { 97 switch t.Size { 98 case 1: 99 defaultValue = fmt.Sprintf("%d", bytes[0]) 100 case 2: 101 defaultValue = fmt.Sprintf("%d", *(*uint16)(unsafe.Pointer(&bytes[0]))) 102 case 4: 103 defaultValue = fmt.Sprintf("%d", *(*uint32)(unsafe.Pointer(&bytes[0]))) 104 case 8: 105 defaultValue = fmt.Sprintf("%d", *(*uint64)(unsafe.Pointer(&bytes[0]))) 106 } 107 } 108 if t.Encoding&btf.Bool != 0 { 109 if defaultValue == "0" { 110 defaultValue = "false" 111 } else { 112 defaultValue = "true" 113 } 114 } 115 } 116 117 i.gadgetCtx.Logger().Debugf("default value for param %q set to %q (%.2X), type was %T", vname, defaultValue, bytes, vtype) 118 119 param.DefaultValue = defaultValue 120 } 121 } 122 return nil 123 } 124 125 // dataSection returns the contents and BTF Datasec descriptor of the spec. 126 // borrowed from cilium/ebpf 127 func dataSection(ms *ebpf.MapSpec) ([]byte, *btf.Datasec, error) { 128 if ms.Value == nil { 129 return nil, nil, errMapNoBTFValue 130 } 131 132 ds, ok := ms.Value.(*btf.Datasec) 133 if !ok { 134 return nil, nil, fmt.Errorf("map value BTF is a %T, not a *btf.Datasec", ms.Value) 135 } 136 137 if n := len(ms.Contents); n != 1 { 138 return nil, nil, fmt.Errorf("expected one key, found %d", n) 139 } 140 141 kv := ms.Contents[0] 142 value, ok := kv.Value.([]byte) 143 if !ok { 144 return nil, nil, fmt.Errorf("value at first map key is %T, not []byte", kv.Value) 145 } 146 147 return value, ds, nil 148 }