package tracer import ( "encoding/binary" "errors" "fmt" "github.com/cilium/ebpf" "github.com/cilium/ebpf/btf" "runtime" ) func kernel_struct_field_offset(btfSpec *btf.Spec, member string, field string) int32 { typ, err := btfSpec.AnyTypeByName(member) if err != nil { return ETR_NOTSUPP } return kernel_struct_field_offset_helper(btfSpec, typ, field) } func kernel_struct_field_offset_helper(btfSpec *btf.Spec, typ btf.Type, field string) int32 { //var offset btf.Bits switch typ.(type) { case *btf.Struct, *btf.Union: var membersT []btf.Member switch t := typ.(type) { case *btf.Struct: membersT = t.Members case *btf.Union: membersT = t.Members } for _, member := range membersT { if member.Name == field { //fmt.Printf("Struct:%s,0x%x\n", member.Name, member.Offset.Bytes()) return int32(member.Offset.Bytes()) } if member.Name == "" { //fmt.Printf("下钻:%s,0x%x\n", member.Type, member.Offset/8) retval := kernel_struct_field_offset_helper(btfSpec, member.Type, field) if retval >= 0 { return int32(member.Offset.Bytes()) + retval } } } } return ETR_NOTEXIST } func bpf_table_pre_set_value(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions, mapName string, data any) int { m, ok := collectionSpec.Maps[mapName] if ok { newMap, err := ebpf.NewMap(&ebpf.MapSpec{ Type: m.Type, KeySize: m.KeySize, ValueSize: m.ValueSize, MaxEntries: m.MaxEntries, }) if err != nil { return ETR_UPDATE_MAP_FAILD } //// Convert test_t to slice //numCPU := runtime.NumCPU() //off := make([]interface{}, numCPU) //for i := range off { // off[i] = data //} key := make([]byte, 4) // Assuming int key size is 4 bytes binary.LittleEndian.PutUint32(key, 0) // Assuming the key is an integer if err = newMap.Update(key, data, ebpf.UpdateAny); err != nil { fmt.Println(err) return ETR_UPDATE_MAP_FAILD } opts.MapReplacements[mapName] = newMap //opts.MapReplacements = map[string]*ebpf.Map{ // mapName: newMap, //} } else { return ETR_UPDATE_MAP_FAILD } return ETR_OK } func bpf_table_set_value(collection *ebpf.Collection, mapName string, key uint32, data any) (int, error) { m, ok := collection.Maps[mapName] //for s, m2 := range collection.Maps { // fmt.Println(s, m2.String()) //} //fmt.Println("bpf_table_set_value", m, mapName, data) if ok { k := make([]byte, 4) // Assuming int k size is 4 bytes binary.LittleEndian.PutUint32(k, key) // Assuming the key is an integer if err := m.Update(k, data, ebpf.UpdateAny); err != nil { return ETR_UPDATE_MAP_FAILD, err } } else { return ETR_UPDATE_MAP_FAILD, errors.New("cannot find map " + mapName) } return ETR_OK, nil } func test(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) { fmt.Println("collectionSpec.Maps start --") var newMap *ebpf.Map var err error m, ok := collectionSpec.Maps["test_heap"] if ok { newMap, err = ebpf.NewMap(&ebpf.MapSpec{ Type: m.Type, // 设置 Map 的类型 KeySize: m.KeySize, // 设置 Key 的大小 ValueSize: m.ValueSize, // 设置 Value 的大小 MaxEntries: m.MaxEntries, // 设置最大条目数 }) if err != nil { fmt.Println("Failed to create map:", err) } data := &testStruct{ test_id: 123123123, } // Convert test_t to slice numCPU := runtime.NumCPU() value := make([]testStruct, numCPU) for i := range value { value[i] = *data } key := make([]byte, 4) // Assuming int key size is 4 bytes binary.LittleEndian.PutUint32(key, 0) // Assuming the key is an integer if err := newMap.Update(key, value, 0); err != nil { panic(err) } opts.MapReplacements["test_heap"] = newMap //opts.MapReplacements = map[string]*ebpf.Map{ // "test_heap": newMap, //} } }