Skip to main content

sbpf_common/
inst_handler.rs

1use crate::{
2    decode::{
3        decode_binary_immediate, decode_binary_register, decode_call_immediate,
4        decode_call_register, decode_endian, decode_exit, decode_jump, decode_jump_immediate,
5        decode_jump_register, decode_jump32_immediate, decode_jump32_register,
6        decode_load_immediate, decode_load_memory, decode_store_immediate, decode_store_register,
7        decode_unary,
8    },
9    errors::{ExecutionError, SBPFError},
10    execute::{
11        Vm, execute_binary_immediate, execute_binary_register, execute_call_immediate,
12        execute_call_register, execute_endian, execute_exit, execute_jump, execute_jump_immediate,
13        execute_jump_register, execute_load_immediate, execute_load_memory,
14        execute_store_immediate, execute_store_register, execute_unary,
15    },
16    instruction::Instruction,
17    opcode::{
18        BIN_IMM_OPS, BIN_REG_OPS, CALL_IMM_OPS, CALL_REG_OPS, ENDIAN_OPS, EXIT_OPS, JUMP_IMM_OPS,
19        JUMP_OPS, JUMP_REG_OPS, JUMP32_IMM_OPS, JUMP32_REG_OPS, LOAD_IMM_OPS, LOAD_MEMORY_OPS,
20        Opcode, OperationType, STORE_IMM_OPS, STORE_REG_OPS, UNARY_OPS,
21    },
22    validate::{
23        validate_binary_immediate, validate_binary_register, validate_call_immediate,
24        validate_call_register, validate_endian, validate_exit, validate_jump,
25        validate_jump_immediate, validate_jump_register, validate_load_immediate,
26        validate_load_memory, validate_store_immediate, validate_store_register, validate_unary,
27    },
28};
29
30type DecodeFn = fn(&[u8]) -> Result<Instruction, SBPFError>;
31type ValidateFn = fn(&Instruction) -> Result<(), SBPFError>;
32pub type ExecuteFn = fn(&mut dyn Vm, &Instruction) -> Result<(), ExecutionError>;
33
34pub struct InstructionHandler {
35    pub decode: DecodeFn,
36    pub validate: ValidateFn,
37    pub execute: ExecuteFn,
38}
39
40use {once_cell::sync::Lazy, std::collections::HashMap};
41
42pub static OPCODE_TO_HANDLER: Lazy<HashMap<Opcode, InstructionHandler>> = Lazy::new(|| {
43    //
44    let mut map = HashMap::new();
45
46    fn register_group(
47        map: &mut HashMap<Opcode, InstructionHandler>,
48        ops: &[Opcode],
49        decode: DecodeFn,
50        validate: ValidateFn,
51        execute: ExecuteFn,
52    ) {
53        for &op in ops {
54            map.insert(
55                op,
56                InstructionHandler {
57                    decode,
58                    validate,
59                    execute,
60                },
61            );
62        }
63    }
64
65    register_group(
66        &mut map,
67        LOAD_IMM_OPS,
68        decode_load_immediate,
69        validate_load_immediate,
70        execute_load_immediate,
71    );
72    register_group(
73        &mut map,
74        LOAD_MEMORY_OPS,
75        decode_load_memory,
76        validate_load_memory,
77        execute_load_memory,
78    );
79    register_group(
80        &mut map,
81        STORE_IMM_OPS,
82        decode_store_immediate,
83        validate_store_immediate,
84        execute_store_immediate,
85    );
86    register_group(
87        &mut map,
88        STORE_REG_OPS,
89        decode_store_register,
90        validate_store_register,
91        execute_store_register,
92    );
93    register_group(
94        &mut map,
95        BIN_IMM_OPS,
96        decode_binary_immediate,
97        validate_binary_immediate,
98        execute_binary_immediate,
99    );
100    register_group(
101        &mut map,
102        BIN_REG_OPS,
103        decode_binary_register,
104        validate_binary_register,
105        execute_binary_register,
106    );
107    register_group(
108        &mut map,
109        UNARY_OPS,
110        decode_unary,
111        validate_unary,
112        execute_unary,
113    );
114    register_group(
115        &mut map,
116        ENDIAN_OPS,
117        decode_endian,
118        validate_endian,
119        execute_endian,
120    );
121    register_group(&mut map, JUMP_OPS, decode_jump, validate_jump, execute_jump);
122    register_group(
123        &mut map,
124        JUMP_IMM_OPS,
125        decode_jump_immediate,
126        validate_jump_immediate,
127        execute_jump_immediate,
128    );
129    register_group(
130        &mut map,
131        JUMP_REG_OPS,
132        decode_jump_register,
133        validate_jump_register,
134        execute_jump_register,
135    );
136    register_group(
137        &mut map,
138        JUMP32_IMM_OPS,
139        decode_jump32_immediate,
140        // validate and execute handlers are shared with JUMP_IMM_OPS
141        validate_jump_immediate,
142        execute_jump_immediate,
143    );
144    register_group(
145        &mut map,
146        JUMP32_REG_OPS,
147        decode_jump32_register,
148        // validate and execute handlers are shared with JUMP_REG_OPS
149        validate_jump_register,
150        execute_jump_register,
151    );
152    register_group(
153        &mut map,
154        CALL_IMM_OPS,
155        decode_call_immediate,
156        validate_call_immediate,
157        execute_call_immediate,
158    );
159    register_group(
160        &mut map,
161        CALL_REG_OPS,
162        decode_call_register,
163        validate_call_register,
164        execute_call_register,
165    );
166    register_group(&mut map, EXIT_OPS, decode_exit, validate_exit, execute_exit);
167
168    map
169});
170
171pub static OPCODE_TO_TYPE: Lazy<HashMap<Opcode, OperationType>> = Lazy::new(|| {
172    let mut map = HashMap::new();
173
174    fn register_group(
175        map: &mut HashMap<Opcode, OperationType>,
176        ops: &[Opcode],
177        op_type: OperationType,
178    ) {
179        for &op in ops {
180            map.insert(op, op_type);
181        }
182    }
183
184    register_group(&mut map, LOAD_IMM_OPS, OperationType::LoadImmediate);
185    register_group(&mut map, LOAD_MEMORY_OPS, OperationType::LoadMemory);
186    register_group(&mut map, STORE_IMM_OPS, OperationType::StoreImmediate);
187    register_group(&mut map, STORE_REG_OPS, OperationType::StoreRegister);
188    register_group(&mut map, BIN_IMM_OPS, OperationType::BinaryImmediate);
189    register_group(&mut map, BIN_REG_OPS, OperationType::BinaryRegister);
190    register_group(&mut map, UNARY_OPS, OperationType::Unary);
191    register_group(&mut map, ENDIAN_OPS, OperationType::Endian);
192    register_group(&mut map, JUMP_OPS, OperationType::Jump);
193    register_group(&mut map, JUMP_IMM_OPS, OperationType::JumpImmediate);
194    register_group(&mut map, JUMP_REG_OPS, OperationType::JumpRegister);
195    register_group(&mut map, JUMP32_IMM_OPS, OperationType::Jump32Immediate);
196    register_group(&mut map, JUMP32_REG_OPS, OperationType::Jump32Register);
197    register_group(&mut map, CALL_IMM_OPS, OperationType::CallImmediate);
198    register_group(&mut map, CALL_REG_OPS, OperationType::CallRegister);
199    register_group(&mut map, EXIT_OPS, OperationType::Exit);
200
201    map
202});