github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/inst_atomic.go (about) 1 package emulator 2 3 import ( 4 "fmt" 5 6 "github.com/dylandreimerink/gobpfld/ebpf" 7 ) 8 9 var _ Instruction = (*AtomicAdd)(nil) 10 11 type AtomicAdd struct { 12 ebpf.AtomicAdd 13 } 14 15 func (i *AtomicAdd) Clone() Instruction { 16 c := *i 17 return &c 18 } 19 20 func (i *AtomicAdd) Execute(vm *VM) error { 21 // TODO make actually atomic using a mutex or similar when adding multi threading support. 22 dr, err := vm.Registers.Copy(i.Dest) 23 if err != nil { 24 return fmt.Errorf("copy %s: %w", i.Dest, err) 25 } 26 27 var off int64 28 var memory Memory 29 switch dmp := dr.(type) { 30 case *MemoryPtr: 31 // Memory pointers point to the start of a memory block 32 off = dmp.Offset + int64(i.Offset) 33 memory = dmp.Memory 34 35 case *FramePointer: 36 // Frame pointers point to the end of a stack frame 37 off = int64(dmp.Memory.Size()) + dmp.Offset + int64(i.Offset) 38 memory = dmp.Memory 39 40 default: 41 return fmt.Errorf("can't store to a non-pointer register value") 42 } 43 44 dv, err := memory.Read(int(off), i.Size) 45 if err != nil { 46 return fmt.Errorf("memory read: %w", err) 47 } 48 49 sr, err := vm.Registers.Get(i.Src) 50 if err != nil { 51 return fmt.Errorf("get src: %w", err) 52 } 53 54 err = dv.Assign(dv.Value() + sr.Value()) 55 if err != nil { 56 return fmt.Errorf("assign value: %w", err) 57 } 58 59 err = memory.Write(int(off), dv, i.Size) 60 if err != nil { 61 return fmt.Errorf("write dst+src: %w", err) 62 } 63 64 return nil 65 }