github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/maps_perf_event_array.go (about) 1 package emulator 2 3 import ( 4 "fmt" 5 6 "github.com/dylandreimerink/gobpfld/bpfsys" 7 "github.com/dylandreimerink/gobpfld/ebpf" 8 ) 9 10 // PerfEventArray is the emulated implementation of BPF_MAP_TYPE_PERF_EVENT_ARRAY. In linux this is a pseudo map type 11 // which is not actually a map, rater a way to one-way data stream using the perf sub system. The userspace program 12 // would have to consume data while it is being produced or risk losing data if the buffer is full. 13 // 14 // This emulated map type has to be consumed by the caller of virtual machine, the event data is stored in a slice 15 // which is currently unlimited in size, it can be read and consumed just like an array map. 16 type PerfEventArray struct { 17 AbstractMap 18 19 Events [][]byte 20 } 21 22 func (m *PerfEventArray) Init() error { 23 return nil 24 } 25 26 func (m *PerfEventArray) Keys() []RegisterValue { 27 keys := make([]RegisterValue, len(m.Events)) 28 for i := range keys { 29 imm := newIMM(int64(i)) 30 keys[i] = &MemoryPtr{ 31 Memory: &ValueMemory{ 32 MemName: fmt.Sprintf("%s[%d]", m.Name, m.Def.ValueSize), 33 Mapping: []RegisterValue{ 34 imm, 35 imm, 36 imm, 37 imm, 38 }, 39 }, 40 } 41 } 42 return keys 43 } 44 45 func (m *PerfEventArray) Lookup(key RegisterValue) (RegisterValue, error) { 46 keyPtr, ok := key.(PointerValue) 47 if !ok { 48 return nil, errMapKeyNoPtr 49 } 50 51 keyValReg, err := keyPtr.Deref(0, ebpf.BPF_W) 52 if !ok { 53 return nil, fmt.Errorf("key pointer deref: %w", err) 54 } 55 56 kv := keyValReg.Value() 57 if int(kv) >= len(m.Events) { 58 return newIMM(0), nil 59 } 60 61 return &MemoryPtr{Memory: &ByteMemory{ 62 MemName: fmt.Sprintf("%s[%d]", m.Name, kv), 63 Backing: m.Events[kv], 64 }, Offset: 0}, nil 65 } 66 67 func (m *PerfEventArray) Update( 68 key RegisterValue, 69 value RegisterValue, 70 flags bpfsys.BPFAttrMapElemFlags, 71 ) ( 72 RegisterValue, 73 error, 74 ) { 75 // Not allowed to update values, since this kind of map is a sort of stream, not an actual map 76 return nil, errMapNotImplemented 77 } 78 79 func (m *PerfEventArray) Delete(key RegisterValue, flags bpfsys.BPFAttrMapElemFlags) error { 80 keyPtr, ok := key.(PointerValue) 81 if !ok { 82 return errMapKeyNoPtr 83 } 84 85 keyValReg, err := keyPtr.Deref(0, ebpf.BPF_W) 86 if !ok { 87 return fmt.Errorf("key pointer deref: %w", err) 88 } 89 90 kv := keyValReg.Value() 91 if int(kv) >= len(m.Events) { 92 return nil 93 } 94 95 copy(m.Events[kv:], m.Events[kv+1:]) 96 m.Events = m.Events[:len(m.Events)-1] 97 98 return nil 99 } 100 101 func (m *PerfEventArray) Push(value RegisterValue, size int64) error { 102 valuePtr, ok := value.(PointerValue) 103 if !ok { 104 return errMapKeyNoPtr 105 } 106 107 val, err := valuePtr.ReadRange(0, int(size)) 108 if !ok { 109 return fmt.Errorf("value pointer read range: %w", err) 110 } 111 112 m.Events = append(m.Events, val) 113 114 return nil 115 }