bpf_ins/
lib.rs

1//! [![Build Status](https://github.com/arcjustin/bpf-ins/workflows/build/badge.svg)](https://github.com/arcjustin/bpf-ins/actions?query=workflow%3Abuild)
2//! [![crates.io](https://img.shields.io/crates/v/bpf-ins.svg)](https://crates.io/crates/bpf-ins)
3//! [![mio](https://docs.rs/bpf-ins/badge.svg)](https://docs.rs/bpf-ins/)
4//! [![Lines of Code](https://tokei.rs/b1/github/arcjustin/bpf-ins?category=code)](https://tokei.rs/b1/github/arcjustin/bpf-ins?category=code)
5//!
6//!
7//! A crate for encoding and decoding eBPF instructions.
8//!
9//! ## Usage
10//!
11//! ```rust
12//! use bpf_ins::{Instruction, Register};
13//!
14//! //
15//! // return 0
16//! //
17//! let instructions = [
18//!     Instruction::mov32(Register::R0, 0), // mov r0, 0
19//!     Instruction::exit(),                 // exit
20//! ];
21//!
22//! let mut encoded = vec![];
23//! for instruction in &instructions {
24//!     let (x, y) = instruction.encode();
25//!     encoded.push(x);
26//!     if let Some(y) = y {
27//!         encoded.push(y);
28//!     }
29//! }
30//! ```
31//!
32//! ## License
33//!
34//! * [MIT license](http://opensource.org/licenses/MIT)
35mod display;
36pub mod error;
37pub mod instruction;
38
39pub use error::*;
40pub use instruction::*;
41
42#[cfg(test)]
43mod tests {
44    use crate::instruction::{Instruction, MemoryOpLoadType, MemoryOpSize, Register};
45
46    fn decode_encode_compare(instruction: &Instruction) {
47        let encoded = instruction.encode();
48
49        let mut raw_instructions = vec![encoded.0];
50        if let Some(n) = encoded.1 {
51            raw_instructions.push(n);
52        }
53
54        let decoded = Instruction::decode(&raw_instructions);
55        if let Ok(new_instruction) = decoded {
56            let reencoded = new_instruction.encode();
57            assert_eq!(encoded, reencoded);
58        } else {
59            panic!("failed to reencode instruction");
60        }
61    }
62
63    #[test]
64    fn arithmetic_add32() {
65        for i in 0..10 {
66            let reg = Register::from_num(i).unwrap();
67
68            let ins = Instruction::add32(reg, i32::min_value());
69            decode_encode_compare(&ins);
70
71            let ins = Instruction::add32(reg, 0);
72            decode_encode_compare(&ins);
73
74            let ins = Instruction::add32(reg, i32::max_value());
75            decode_encode_compare(&ins);
76        }
77    }
78
79    #[test]
80    fn arithmetic_add64() {
81        for i in 0..10 {
82            let reg = Register::from_num(i).unwrap();
83
84            let ins = Instruction::add64(reg, i32::min_value());
85            decode_encode_compare(&ins);
86
87            let ins = Instruction::add64(reg, 0);
88            decode_encode_compare(&ins);
89
90            let ins = Instruction::add64(reg, i32::max_value());
91            decode_encode_compare(&ins);
92        }
93    }
94
95    #[test]
96    fn arithmetic_addx32() {
97        for i in 0..10 {
98            for j in 0..10 {
99                let dst_reg = Register::from_num(i).unwrap();
100                let src_reg = Register::from_num(j).unwrap();
101
102                let ins = Instruction::addx32(dst_reg, src_reg);
103                decode_encode_compare(&ins);
104            }
105        }
106    }
107
108    #[test]
109    fn arithmetic_addx64() {
110        for i in 0..10 {
111            for j in 0..10 {
112                let dst_reg = Register::from_num(i).unwrap();
113                let src_reg = Register::from_num(j).unwrap();
114
115                let ins = Instruction::addx64(dst_reg, src_reg);
116                decode_encode_compare(&ins);
117            }
118        }
119    }
120
121    #[test]
122    fn arithmetic_mov32() {
123        for i in 0..10 {
124            let reg = Register::from_num(i).unwrap();
125
126            let ins = Instruction::mov32(reg, i32::min_value());
127            decode_encode_compare(&ins);
128
129            let ins = Instruction::mov32(reg, 0);
130            decode_encode_compare(&ins);
131
132            let ins = Instruction::mov32(reg, i32::max_value());
133            decode_encode_compare(&ins);
134        }
135    }
136
137    #[test]
138    fn arithmetic_mov64() {
139        for i in 0..10 {
140            let reg = Register::from_num(i).unwrap();
141
142            let ins = Instruction::mov64(reg, i32::min_value());
143            decode_encode_compare(&ins);
144
145            let ins = Instruction::mov64(reg, 0);
146            decode_encode_compare(&ins);
147
148            let ins = Instruction::mov64(reg, i32::max_value());
149            decode_encode_compare(&ins);
150        }
151    }
152
153    #[test]
154    fn arithmetic_movx32() {
155        for i in 0..10 {
156            for j in 0..10 {
157                let dst_reg = Register::from_num(i).unwrap();
158                let src_reg = Register::from_num(j).unwrap();
159
160                let ins = Instruction::movx32(dst_reg, src_reg);
161                decode_encode_compare(&ins);
162            }
163        }
164    }
165
166    #[test]
167    fn arithmetic_movx64() {
168        for i in 0..10 {
169            for j in 0..10 {
170                let dst_reg = Register::from_num(i).unwrap();
171                let src_reg = Register::from_num(j).unwrap();
172
173                let ins = Instruction::movx64(dst_reg, src_reg);
174                decode_encode_compare(&ins);
175            }
176        }
177    }
178
179    #[test]
180    fn memory_load() {
181        for i in 0..10 {
182            let reg = Register::from_num(i).unwrap();
183
184            let ins = Instruction::load(reg, i64::min_value(), MemoryOpSize::Byte);
185            decode_encode_compare(&ins);
186
187            let ins = Instruction::load(reg, i64::max_value(), crate::MemoryOpSize::HalfWord);
188            decode_encode_compare(&ins);
189
190            let ins = Instruction::load(reg, 0, MemoryOpSize::Word);
191            decode_encode_compare(&ins);
192
193            let ins = Instruction::load(reg, 1, MemoryOpSize::DoubleWord);
194            decode_encode_compare(&ins);
195        }
196    }
197
198    #[test]
199    fn memory_loadx() {
200        for i in 0..10 {
201            for j in 0..10 {
202                let dst_reg = Register::from_num(i).unwrap();
203                let src_reg = Register::from_num(j).unwrap();
204
205                let ins = Instruction::loadx8(dst_reg, src_reg, i16::min_value());
206                decode_encode_compare(&ins);
207
208                let ins = Instruction::loadx8(dst_reg, src_reg, 0);
209                decode_encode_compare(&ins);
210
211                let ins = Instruction::loadx8(dst_reg, src_reg, i16::max_value());
212                decode_encode_compare(&ins);
213
214                let ins = Instruction::loadx16(dst_reg, src_reg, i16::min_value());
215                decode_encode_compare(&ins);
216
217                let ins = Instruction::loadx16(dst_reg, src_reg, 0);
218                decode_encode_compare(&ins);
219
220                let ins = Instruction::loadx16(dst_reg, src_reg, i16::max_value());
221                decode_encode_compare(&ins);
222
223                let ins = Instruction::loadx32(dst_reg, src_reg, i16::min_value());
224                decode_encode_compare(&ins);
225
226                let ins = Instruction::loadx32(dst_reg, src_reg, 0);
227                decode_encode_compare(&ins);
228
229                let ins = Instruction::loadx32(dst_reg, src_reg, i16::max_value());
230                decode_encode_compare(&ins);
231
232                let ins = Instruction::loadx64(dst_reg, src_reg, i16::min_value());
233                decode_encode_compare(&ins);
234
235                let ins = Instruction::loadx64(dst_reg, src_reg, 0);
236                decode_encode_compare(&ins);
237
238                let ins = Instruction::loadx64(dst_reg, src_reg, i16::max_value());
239                decode_encode_compare(&ins);
240            }
241        }
242    }
243
244    #[test]
245    fn memory_store() {
246        for i in 0..10 {
247            let reg = Register::from_num(i).unwrap();
248
249            let ins = Instruction::store8(reg, i16::min_value(), i8::min_value());
250            decode_encode_compare(&ins);
251
252            let ins = Instruction::store8(reg, 0, 0);
253            decode_encode_compare(&ins);
254
255            let ins = Instruction::store8(reg, i16::max_value(), i8::max_value());
256            decode_encode_compare(&ins);
257
258            let ins = Instruction::store16(reg, i16::min_value(), i16::min_value());
259            decode_encode_compare(&ins);
260
261            let ins = Instruction::store16(reg, 0, 0);
262            decode_encode_compare(&ins);
263
264            let ins = Instruction::store16(reg, i16::max_value(), i16::max_value());
265            decode_encode_compare(&ins);
266
267            let ins = Instruction::store32(reg, i16::min_value(), i32::min_value());
268            decode_encode_compare(&ins);
269
270            let ins = Instruction::store32(reg, 0, 0);
271            decode_encode_compare(&ins);
272
273            let ins = Instruction::store32(reg, i16::max_value(), i32::max_value());
274            decode_encode_compare(&ins);
275
276            let ins = Instruction::store64(reg, i16::min_value(), i64::min_value());
277            decode_encode_compare(&ins);
278
279            let ins = Instruction::store64(reg, 0, 0);
280            decode_encode_compare(&ins);
281
282            let ins = Instruction::store64(reg, i16::max_value(), i64::max_value());
283            decode_encode_compare(&ins);
284        }
285    }
286
287    #[test]
288    fn memory_storex() {
289        for i in 0..10 {
290            for j in 0..10 {
291                let dst_reg = Register::from_num(i).unwrap();
292                let src_reg = Register::from_num(j).unwrap();
293
294                let ins = Instruction::storex8(dst_reg, i16::min_value(), src_reg);
295                decode_encode_compare(&ins);
296
297                let ins = Instruction::storex8(dst_reg, 0, src_reg);
298                decode_encode_compare(&ins);
299
300                let ins = Instruction::storex8(dst_reg, i16::max_value(), src_reg);
301                decode_encode_compare(&ins);
302
303                let ins = Instruction::storex16(dst_reg, i16::min_value(), src_reg);
304                decode_encode_compare(&ins);
305
306                let ins = Instruction::storex16(dst_reg, 0, src_reg);
307                decode_encode_compare(&ins);
308
309                let ins = Instruction::storex16(dst_reg, i16::max_value(), src_reg);
310                decode_encode_compare(&ins);
311
312                let ins = Instruction::storex32(dst_reg, i16::min_value(), src_reg);
313                decode_encode_compare(&ins);
314
315                let ins = Instruction::storex32(dst_reg, 0, src_reg);
316                decode_encode_compare(&ins);
317
318                let ins = Instruction::storex32(dst_reg, i16::max_value(), src_reg);
319                decode_encode_compare(&ins);
320
321                let ins = Instruction::storex64(dst_reg, i16::min_value(), src_reg);
322                decode_encode_compare(&ins);
323
324                let ins = Instruction::storex64(dst_reg, 0, src_reg);
325                decode_encode_compare(&ins);
326
327                let ins = Instruction::storex64(dst_reg, i16::max_value(), src_reg);
328                decode_encode_compare(&ins);
329            }
330        }
331    }
332
333    #[test]
334    fn loadtype() {
335        for i in 0..10 {
336            let reg = Register::from_num(i).unwrap();
337
338            let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::Void);
339            decode_encode_compare(&ins);
340
341            let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::Void);
342            decode_encode_compare(&ins);
343
344            let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::Void);
345            decode_encode_compare(&ins);
346
347            let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::Map);
348            decode_encode_compare(&ins);
349
350            let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::Map);
351            decode_encode_compare(&ins);
352
353            let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::Map);
354            decode_encode_compare(&ins);
355
356            let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::MapValue);
357            decode_encode_compare(&ins);
358
359            let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::MapValue);
360            decode_encode_compare(&ins);
361
362            let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::MapValue);
363            decode_encode_compare(&ins);
364
365            let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::BtfId);
366            decode_encode_compare(&ins);
367
368            let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::BtfId);
369            decode_encode_compare(&ins);
370
371            let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::BtfId);
372            decode_encode_compare(&ins);
373
374            let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::Function);
375            decode_encode_compare(&ins);
376
377            let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::Function);
378            decode_encode_compare(&ins);
379
380            let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::Function);
381            decode_encode_compare(&ins);
382
383            let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::MapIndex);
384            decode_encode_compare(&ins);
385
386            let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::MapIndex);
387            decode_encode_compare(&ins);
388
389            let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::MapIndex);
390            decode_encode_compare(&ins);
391
392            let ins = Instruction::loadtype(reg, i64::min_value(), MemoryOpLoadType::MapIndexValue);
393            decode_encode_compare(&ins);
394
395            let ins = Instruction::loadtype(reg, 0, MemoryOpLoadType::MapIndexValue);
396            decode_encode_compare(&ins);
397
398            let ins = Instruction::loadtype(reg, i64::max_value(), MemoryOpLoadType::MapIndexValue);
399            decode_encode_compare(&ins);
400        }
401    }
402
403    #[test]
404    fn call() {
405        let ins = Instruction::call(0);
406        decode_encode_compare(&ins);
407
408        let ins = Instruction::call(u32::max_value());
409        decode_encode_compare(&ins);
410    }
411
412    #[test]
413    fn exit() {
414        let ins = Instruction::exit();
415        decode_encode_compare(&ins);
416    }
417}