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

     1  package emulator
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/dylandreimerink/gobpfld/ebpf"
     7  )
     8  
     9  var _ Instruction = (*Exit)(nil)
    10  
    11  type Exit struct {
    12  	ebpf.Exit
    13  }
    14  
    15  var errExit = errors.New("function/program exit")
    16  
    17  func (i *Exit) Clone() Instruction {
    18  	c := *i
    19  	return &c
    20  }
    21  
    22  func (i *Exit) Execute(vm *VM) error {
    23  	// If the call stack is empty, we exit the program
    24  	if len(vm.PreservedRegisters) == 0 {
    25  		return errExit
    26  	}
    27  
    28  	// If there are values on the call stack, this is a return statement
    29  	preserved := vm.PreservedRegisters[len(vm.PreservedRegisters)-1]
    30  	vm.PreservedRegisters = vm.PreservedRegisters[:len(vm.PreservedRegisters)-1]
    31  
    32  	// Restore preserved Program counter and callee saved registers
    33  	vm.Registers.PC = preserved.PC
    34  	vm.Registers.R6 = preserved.R6
    35  	vm.Registers.R7 = preserved.R7
    36  	vm.Registers.R8 = preserved.R8
    37  	vm.Registers.R9 = preserved.R9
    38  
    39  	// Restore the previous stack frame
    40  	vm.Registers.R10 = FramePointer{
    41  		Memory:   &vm.StackFrames[vm.Registers.R10.Index-1],
    42  		Index:    vm.Registers.R10.Index - 1,
    43  		Offset:   0,
    44  		Readonly: true,
    45  	}
    46  
    47  	return nil
    48  }