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

     1  package emulator
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/dylandreimerink/gobpfld/ebpf"
     8  )
     9  
    10  // Instruction represents an eBPF instruction, as apposed to the ebpf.Instruction interface, these instruction can
    11  // actually be executed by an emulator VM.
    12  type Instruction interface {
    13  	ebpf.Instruction
    14  
    15  	Clone() Instruction
    16  	Execute(vm *VM) error
    17  }
    18  
    19  // Translate translates the High level instructions of the ebpf package and embeds them into instructions defined
    20  // by the emulator package. The emulator instructions contain the logic to actually execute them.
    21  func Translate(prog []ebpf.Instruction) ([]Instruction, error) {
    22  	vmProg := make([]Instruction, len(prog))
    23  
    24  	for i, intInst := range prog {
    25  		var newInst Instruction
    26  
    27  		switch inst := intInst.(type) {
    28  		case *ebpf.Add32:
    29  			newInst = &Add32{Add32: *inst}
    30  		case *ebpf.Add64:
    31  			newInst = &Add64{Add64: *inst}
    32  		case *ebpf.Add32Register:
    33  			newInst = &Add32Register{Add32Register: *inst}
    34  		case *ebpf.Add64Register:
    35  			newInst = &Add64Register{Add64Register: *inst}
    36  		case *ebpf.And32:
    37  			newInst = &And32{And32: *inst}
    38  		case *ebpf.And64:
    39  			newInst = &And64{And64: *inst}
    40  		case *ebpf.And32Register:
    41  			newInst = &And32Register{And32Register: *inst}
    42  		case *ebpf.And64Register:
    43  			newInst = &And64Register{And64Register: *inst}
    44  		case *ebpf.ARSH32:
    45  			newInst = &ARSH32{ARSH32: *inst}
    46  		case *ebpf.ARSH64:
    47  			newInst = &ARSH64{ARSH64: *inst}
    48  		case *ebpf.ARSH32Register:
    49  			newInst = &ARSH32Register{ARSH32Register: *inst}
    50  		case *ebpf.ARSH64Register:
    51  			newInst = &ARSH64Register{ARSH64Register: *inst}
    52  		case *ebpf.AtomicAdd:
    53  			newInst = &AtomicAdd{AtomicAdd: *inst}
    54  		case *ebpf.CallBPF:
    55  			newInst = &CallBPF{CallBPF: *inst}
    56  		case *ebpf.CallHelper:
    57  			newInst = &CallHelper{CallHelper: *inst}
    58  		case *ebpf.CallHelperIndirect:
    59  			newInst = &CallHelperIndirect{CallHelperIndirect: *inst}
    60  		case *ebpf.Div32:
    61  			newInst = &Div32{Div32: *inst}
    62  		case *ebpf.Div64:
    63  			newInst = &Div64{Div64: *inst}
    64  		case *ebpf.Div32Register:
    65  			newInst = &Div32Register{Div32Register: *inst}
    66  		case *ebpf.Div64Register:
    67  			newInst = &Div64Register{Div64Register: *inst}
    68  		case *ebpf.End16ToLE:
    69  			newInst = &End16ToLE{End16ToLE: *inst}
    70  		case *ebpf.End32ToLE:
    71  			newInst = &End32ToLE{End32ToLE: *inst}
    72  		case *ebpf.End64ToLE:
    73  			newInst = &End64ToLE{End64ToLE: *inst}
    74  		case *ebpf.End16ToBE:
    75  			newInst = &End16ToBE{End16ToBE: *inst}
    76  		case *ebpf.End32ToBE:
    77  			newInst = &End32ToBE{End32ToBE: *inst}
    78  		case *ebpf.End64ToBE:
    79  			newInst = &End64ToBE{End64ToBE: *inst}
    80  		case *ebpf.Exit:
    81  			newInst = &Exit{Exit: *inst}
    82  		case *ebpf.Jump:
    83  			newInst = &Jump{Jump: *inst}
    84  		case *ebpf.JumpEqual:
    85  			newInst = &JumpEqual{JumpEqual: *inst}
    86  		case *ebpf.JumpEqual32:
    87  			newInst = &JumpEqual32{JumpEqual32: *inst}
    88  		case *ebpf.JumpEqualRegister:
    89  			newInst = &JumpEqualRegister{JumpEqualRegister: *inst}
    90  		case *ebpf.JumpEqualRegister32:
    91  			newInst = &JumpEqualRegister32{JumpEqualRegister32: *inst}
    92  		case *ebpf.JumpNotEqual:
    93  			newInst = &JumpNotEqual{JumpNotEqual: *inst}
    94  		case *ebpf.JumpNotEqual32:
    95  			newInst = &JumpNotEqual32{JumpNotEqual32: *inst}
    96  		case *ebpf.JumpNotEqualRegister:
    97  			newInst = &JumpNotEqualRegister{JumpNotEqualRegister: *inst}
    98  		case *ebpf.JumpNotEqualRegister32:
    99  			newInst = &JumpNotEqualRegister32{JumpNotEqualRegister32: *inst}
   100  		case *ebpf.JumpGreaterThanEqual:
   101  			newInst = &JumpGreaterThanEqual{JumpGreaterThanEqual: *inst}
   102  		case *ebpf.JumpGreaterThanEqual32:
   103  			newInst = &JumpGreaterThanEqual32{JumpGreaterThanEqual32: *inst}
   104  		case *ebpf.JumpGreaterThanEqualRegister:
   105  			newInst = &JumpGreaterThanEqualRegister{JumpGreaterThanEqualRegister: *inst}
   106  		case *ebpf.JumpGreaterThanEqualRegister32:
   107  			newInst = &JumpGreaterThanEqualRegister32{JumpGreaterThanEqualRegister32: *inst}
   108  		case *ebpf.JumpGreaterThan:
   109  			newInst = &JumpGreaterThan{JumpGreaterThan: *inst}
   110  		case *ebpf.JumpGreaterThan32:
   111  			newInst = &JumpGreaterThan32{JumpGreaterThan32: *inst}
   112  		case *ebpf.JumpGreaterThanRegister:
   113  			newInst = &JumpGreaterThanRegister{JumpGreaterThanRegister: *inst}
   114  		case *ebpf.JumpGreaterThanRegister32:
   115  			newInst = &JumpGreaterThanRegister32{JumpGreaterThanRegister32: *inst}
   116  		case *ebpf.JumpSignedGreaterThanOrEqual:
   117  			newInst = &JumpSignedGreaterThanOrEqual{JumpSignedGreaterThanOrEqual: *inst}
   118  		case *ebpf.JumpSignedGreaterThanOrEqual32:
   119  			newInst = &JumpSignedGreaterThanOrEqual32{JumpSignedGreaterThanOrEqual32: *inst}
   120  		case *ebpf.JumpSignedGreaterThanOrEqualRegister:
   121  			newInst = &JumpSignedGreaterThanOrEqualRegister{JumpSignedGreaterThanOrEqualRegister: *inst}
   122  		case *ebpf.JumpSignedGreaterThanOrEqualRegister32:
   123  			newInst = &JumpSignedGreaterThanOrEqualRegister32{JumpSignedGreaterThanOrEqualRegister32: *inst}
   124  		case *ebpf.JumpSignedGreaterThan:
   125  			newInst = &JumpSignedGreaterThan{JumpSignedGreaterThan: *inst}
   126  		case *ebpf.JumpSignedGreaterThan32:
   127  			newInst = &JumpSignedGreaterThan32{JumpSignedGreaterThan32: *inst}
   128  		case *ebpf.JumpSignedGreaterThanRegister:
   129  			newInst = &JumpSignedGreaterThanRegister{JumpSignedGreaterThanRegister: *inst}
   130  		case *ebpf.JumpSignedGreaterThanRegister32:
   131  			newInst = &JumpSignedGreaterThanRegister32{JumpSignedGreaterThanRegister32: *inst}
   132  		case *ebpf.JumpSignedSmallerThanOrEqual:
   133  			newInst = &JumpSignedSmallerThanOrEqual{JumpSignedSmallerThanOrEqual: *inst}
   134  		case *ebpf.JumpSignedSmallerThanOrEqual32:
   135  			newInst = &JumpSignedSmallerThanOrEqual32{JumpSignedSmallerThanOrEqual32: *inst}
   136  		case *ebpf.JumpSignedSmallerThanOrEqualRegister:
   137  			newInst = &JumpSignedSmallerThanOrEqualRegister{JumpSignedSmallerThanOrEqualRegister: *inst}
   138  		case *ebpf.JumpSignedSmallerThanOrEqualRegister32:
   139  			newInst = &JumpSignedSmallerThanOrEqualRegister32{JumpSignedSmallerThanOrEqualRegister32: *inst}
   140  		case *ebpf.JumpSignedSmallerThan:
   141  			newInst = &JumpSignedSmallerThan{JumpSignedSmallerThan: *inst}
   142  		case *ebpf.JumpSignedSmallerThan32:
   143  			newInst = &JumpSignedSmallerThan32{JumpSignedSmallerThan32: *inst}
   144  		case *ebpf.JumpSignedSmallerThanRegister:
   145  			newInst = &JumpSignedSmallerThanRegister{JumpSignedSmallerThanRegister: *inst}
   146  		case *ebpf.JumpSignedSmallerThanRegister32:
   147  			newInst = &JumpSignedSmallerThanRegister32{JumpSignedSmallerThanRegister32: *inst}
   148  		case *ebpf.LoadConstant64bit:
   149  			newInst = &LoadConstant64bit{LoadConstant64bit: *inst}
   150  		case *ebpf.LoadMemory:
   151  			newInst = &LoadMemory{LoadMemory: *inst}
   152  		case *ebpf.LoadSocketBuf:
   153  			newInst = &LoadSocketBuf{LoadSocketBuf: *inst}
   154  		case *ebpf.LoadSocketBufConstant:
   155  			newInst = &LoadSocketBufConstant{LoadSocketBufConstant: *inst}
   156  		case *ebpf.Lsh32:
   157  			newInst = &Lsh32{Lsh32: *inst}
   158  		case *ebpf.Lsh64:
   159  			newInst = &Lsh64{Lsh64: *inst}
   160  		case *ebpf.Lsh32Register:
   161  			newInst = &Lsh32Register{Lsh32Register: *inst}
   162  		case *ebpf.Lsh64Register:
   163  			newInst = &Lsh64Register{Lsh64Register: *inst}
   164  		case *ebpf.Mod32:
   165  			newInst = &Mod32{Mod32: *inst}
   166  		case *ebpf.Mod64:
   167  			newInst = &Mod64{Mod64: *inst}
   168  		case *ebpf.Mod32Register:
   169  			newInst = &Mod32Register{Mod32Register: *inst}
   170  		case *ebpf.Mod64Register:
   171  			newInst = &Mod64Register{Mod64Register: *inst}
   172  		case *ebpf.Mov32:
   173  			newInst = &Mov32{Mov32: *inst}
   174  		case *ebpf.Mov64:
   175  			newInst = &Mov64{Mov64: *inst}
   176  		case *ebpf.Mov32Register:
   177  			newInst = &Mov32Register{Mov32Register: *inst}
   178  		case *ebpf.Mov64Register:
   179  			newInst = &Mov64Register{Mov64Register: *inst}
   180  		case *ebpf.Mul32:
   181  			newInst = &Mul32{Mul32: *inst}
   182  		case *ebpf.Mul64:
   183  			newInst = &Mul64{Mul64: *inst}
   184  		case *ebpf.Mul32Register:
   185  			newInst = &Mul32Register{Mul32Register: *inst}
   186  		case *ebpf.Mul64Register:
   187  			newInst = &Mul64Register{Mul64Register: *inst}
   188  		case *ebpf.Neg32:
   189  			newInst = &Neg32{Neg32: *inst}
   190  		case *ebpf.Neg64:
   191  			newInst = &Neg64{Neg64: *inst}
   192  		case *ebpf.Nop:
   193  			newInst = &Nop{Nop: *inst}
   194  		case *ebpf.Or32:
   195  			newInst = &Or32{Or32: *inst}
   196  		case *ebpf.Or64:
   197  			newInst = &Or64{Or64: *inst}
   198  		case *ebpf.Or32Register:
   199  			newInst = &Or32Register{Or32Register: *inst}
   200  		case *ebpf.Or64Register:
   201  			newInst = &Or64Register{Or64Register: *inst}
   202  		case *ebpf.Rsh32:
   203  			newInst = &Rsh32{Rsh32: *inst}
   204  		case *ebpf.Rsh64:
   205  			newInst = &Rsh64{Rsh64: *inst}
   206  		case *ebpf.Rsh32Register:
   207  			newInst = &Rsh32Register{Rsh32Register: *inst}
   208  		case *ebpf.Rsh64Register:
   209  			newInst = &Rsh64Register{Rsh64Register: *inst}
   210  		case *ebpf.StoreMemoryConstant:
   211  			newInst = &StoreMemoryConstant{StoreMemoryConstant: *inst}
   212  		case *ebpf.StoreMemoryRegister:
   213  			newInst = &StoreMemoryRegister{StoreMemoryRegister: *inst}
   214  		case *ebpf.Sub32:
   215  			newInst = &Sub32{Sub32: *inst}
   216  		case *ebpf.Sub64:
   217  			newInst = &Sub64{Sub64: *inst}
   218  		case *ebpf.Sub32Register:
   219  			newInst = &Sub32Register{Sub32Register: *inst}
   220  		case *ebpf.Sub64Register:
   221  			newInst = &Sub64Register{Sub64Register: *inst}
   222  		case *ebpf.Xor32:
   223  			newInst = &Xor32{Xor32: *inst}
   224  		case *ebpf.Xor64:
   225  			newInst = &Xor64{Xor64: *inst}
   226  		case *ebpf.Xor32Register:
   227  			newInst = &Xor32Register{Xor32Register: *inst}
   228  		case *ebpf.Xor64Register:
   229  			newInst = &Xor64Register{Xor64Register: *inst}
   230  		default:
   231  			return nil, fmt.Errorf("can't translate instruction at %d of type %T", i, inst)
   232  		}
   233  
   234  		vmProg[i] = newInst
   235  	}
   236  
   237  	return vmProg, nil
   238  }
   239  
   240  func readReg(vm *VM, reg ebpf.Register) (int64, RegisterValue, error) {
   241  	r, err := vm.Registers.Get(reg)
   242  	if err != nil {
   243  		return 0, r, fmt.Errorf("get %s: %w", reg.String(), err)
   244  	}
   245  
   246  	return r.Value(), r, err
   247  }
   248  
   249  func isIMM(r RegisterValue) bool {
   250  	_, ok := r.(*IMMValue)
   251  	return ok
   252  }
   253  
   254  func sameRVType(a, b RegisterValue) bool {
   255  	at := reflect.TypeOf(a)
   256  	bt := reflect.TypeOf(b)
   257  	return at == bt
   258  }