github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/inst_load.go (about) 1 package emulator 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/dylandreimerink/gobpfld/ebpf" 8 ) 9 10 var _ Instruction = (*LoadConstant64bit)(nil) 11 12 type LoadConstant64bit struct { 13 ebpf.LoadConstant64bit 14 } 15 16 func (i *LoadConstant64bit) Clone() Instruction { 17 c := *i 18 return &c 19 } 20 21 func (i *LoadConstant64bit) Execute(vm *VM) error { 22 dr, err := vm.Registers.Get(i.Dest) 23 if err != nil { 24 return fmt.Errorf("get: %w", err) 25 } 26 27 if i.Src == ebpf.BPF_PSEUDO_MAP_FD { 28 err = vm.Registers.Assign(i.Dest, newIMM(int64(i.Val1))) 29 if err != nil { 30 return fmt.Errorf("assign register: %w", err) 31 } 32 33 return nil 34 } 35 36 if i.Src == ebpf.BPF_PSEUDO_MAP_FD_VALUE { 37 // This is a special load instruction which will return an offset into the value of key 0 of a map. 38 // It is only used to access ELF data sections. 39 40 if int(i.Val1) >= len(vm.Maps) { 41 return fmt.Errorf("no map loaded at index '%d'", i.Val1) 42 } 43 44 m := vm.Maps[i.Val1] 45 mapValue, err := m.Lookup(&MemoryPtr{Memory: &ByteMemory{MemName: "(tmp mem)", Backing: make([]byte, 4)}}) 46 if err != nil { 47 return fmt.Errorf("map lookup: %w", err) 48 } 49 50 mapValuePtr, ok := mapValue.(*MemoryPtr) 51 if !ok { 52 return fmt.Errorf("map lookup didn't return a memory pointer") 53 } 54 55 mapValuePtr.Offset = int64(i.Val2) 56 57 err = vm.Registers.Assign(i.Dest, mapValuePtr) 58 if err != nil { 59 return fmt.Errorf("assign register: %w", err) 60 } 61 62 return nil 63 } 64 65 err = dr.Assign(int64(i.Val2)<<32 + int64(i.Val1)) 66 if err != nil { 67 return fmt.Errorf("assign value: %w", err) 68 } 69 70 return nil 71 } 72 73 var _ Instruction = (*LoadMemory)(nil) 74 75 type LoadMemory struct { 76 ebpf.LoadMemory 77 } 78 79 func (i *LoadMemory) Clone() Instruction { 80 c := *i 81 return &c 82 } 83 84 func (i *LoadMemory) Execute(vm *VM) error { 85 sr, err := vm.Registers.Copy(i.Src) 86 if err != nil { 87 return fmt.Errorf("copy %s: %w", i.Dest, err) 88 } 89 90 var off int64 91 var memory Memory 92 switch smp := sr.(type) { 93 case *MemoryPtr: 94 // Memory pointers point to the start of a memory block 95 off = smp.Offset + int64(i.Offset) 96 memory = smp.Memory 97 98 case *FramePointer: 99 // Frame pointers point to the end of a stack frame 100 off = int64(smp.Memory.Size()) + smp.Offset + int64(i.Offset) 101 memory = smp.Memory 102 103 default: 104 return fmt.Errorf("can't read from a non-pointer register value") 105 } 106 107 val, err := memory.Read(int(off), i.Size) 108 if err != nil { 109 return fmt.Errorf("read from memory: %w", err) 110 } 111 112 err = vm.Registers.Assign(i.Dest, val) 113 if err != nil { 114 return fmt.Errorf("assign '%s': %w", i.Dest, err) 115 } 116 117 return nil 118 } 119 120 var _ Instruction = (*LoadSocketBuf)(nil) 121 122 type LoadSocketBuf struct { 123 ebpf.LoadSocketBuf 124 } 125 126 func (i *LoadSocketBuf) Clone() Instruction { 127 c := *i 128 return &c 129 } 130 131 func (i *LoadSocketBuf) Execute(vm *VM) error { 132 return errors.New("not implemented") 133 } 134 135 var _ Instruction = (*LoadSocketBuf)(nil) 136 137 type LoadSocketBufConstant struct { 138 ebpf.LoadSocketBufConstant 139 } 140 141 func (i *LoadSocketBufConstant) Clone() Instruction { 142 c := *i 143 return &c 144 } 145 146 func (i *LoadSocketBufConstant) Execute(vm *VM) error { 147 return errors.New("not implemented") 148 }