github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/inst_add.go (about)

     1  package emulator
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/dylandreimerink/gobpfld/ebpf"
     7  )
     8  
     9  var _ Instruction = (*Add32)(nil)
    10  
    11  type Add32 struct {
    12  	ebpf.Add32
    13  }
    14  
    15  func (i *Add32) Clone() Instruction {
    16  	c := *i
    17  	return &c
    18  }
    19  
    20  func (i *Add32) Execute(vm *VM) error {
    21  	rv, r, err := readReg(vm, i.Dest)
    22  	if err != nil {
    23  		return err
    24  	}
    25  
    26  	err = r.Assign(int64(int32(rv) + i.Value))
    27  	if err != nil {
    28  		return fmt.Errorf("assign value  %s: %w", i.Dest.String(), err)
    29  	}
    30  
    31  	return nil
    32  }
    33  
    34  var _ Instruction = (*Add64)(nil)
    35  
    36  type Add64 struct {
    37  	ebpf.Add64
    38  }
    39  
    40  func (i *Add64) Clone() Instruction {
    41  	c := *i
    42  	return &c
    43  }
    44  
    45  func (i *Add64) Execute(vm *VM) error {
    46  	rv, r, err := readReg(vm, i.Dest)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	err = r.Assign(rv + int64(i.Value))
    52  	if err != nil {
    53  		return fmt.Errorf("assign value  %s: %w", i.Dest.String(), err)
    54  	}
    55  
    56  	return nil
    57  }
    58  
    59  var _ Instruction = (*Add32Register)(nil)
    60  
    61  type Add32Register struct {
    62  	ebpf.Add32Register
    63  }
    64  
    65  func (i *Add32Register) Clone() Instruction {
    66  	c := *i
    67  	return &c
    68  }
    69  
    70  func (i *Add32Register) Execute(vm *VM) error {
    71  	dv, dr, err := readReg(vm, i.Dest)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	sv, sr, err := readReg(vm, i.Src)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	// Edge case: if we add a pointer to a value, we want to convert the destination type into a pointer as well
    82  	if _, ok := sr.(PointerValue); ok {
    83  		scp, err := vm.Registers.Copy(i.Src)
    84  		if err != nil {
    85  			return err
    86  		}
    87  
    88  		err = scp.Assign(int64(int32(dv) + int32(sv)))
    89  		if err != nil {
    90  			return err
    91  		}
    92  
    93  		err = vm.Registers.Assign(i.Dest, scp)
    94  		if err != nil {
    95  			return err
    96  		}
    97  		return nil
    98  	}
    99  
   100  	err = dr.Assign(int64(int32(dv) + int32(sv)))
   101  	if err != nil {
   102  		return fmt.Errorf("assign value %s: %w", i.Dest.String(), err)
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  var _ Instruction = (*Add64Register)(nil)
   109  
   110  type Add64Register struct {
   111  	ebpf.Add64Register
   112  }
   113  
   114  func (i *Add64Register) Clone() Instruction {
   115  	c := *i
   116  	return &c
   117  }
   118  
   119  func (i *Add64Register) Execute(vm *VM) error {
   120  	dv, dr, err := readReg(vm, i.Dest)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	sv, sr, err := readReg(vm, i.Src)
   126  	if err != nil {
   127  		return err
   128  	}
   129  
   130  	// Edge case: if we add a pointer to a value, we want to convert the destination type into a pointer as well
   131  	if _, ok := sr.(PointerValue); ok {
   132  		scp, err := vm.Registers.Copy(i.Src)
   133  		if err != nil {
   134  			return err
   135  		}
   136  
   137  		err = scp.Assign(dv + sv)
   138  		if err != nil {
   139  			return err
   140  		}
   141  
   142  		err = vm.Registers.Assign(i.Dest, scp)
   143  		if err != nil {
   144  			return err
   145  		}
   146  		return nil
   147  	}
   148  
   149  	err = dr.Assign(dv + sv)
   150  	if err != nil {
   151  		return fmt.Errorf("assign value %s: %w", i.Dest.String(), err)
   152  	}
   153  
   154  	return nil
   155  }