insn_builder.rs 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563
  1. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
  2. // Copyright 2017 Alex Dukhno <alex.dukhno@icloud.com>
  3. //! Module provides API to create eBPF programs by Rust programming language
  4. use ebpf::*;
  5. use crate::lib::*;
  6. /// Represents single eBPF instruction
  7. pub trait Instruction: Sized {
  8. /// returns instruction opt code
  9. fn opt_code_byte(&self) -> u8;
  10. /// returns destination register
  11. fn get_dst(&self) -> u8 {
  12. self.get_insn().dst
  13. }
  14. /// returns source register
  15. fn get_src(&self) -> u8 {
  16. self.get_insn().src
  17. }
  18. /// returns offset bytes
  19. fn get_off(&self) -> i16 {
  20. self.get_insn().off
  21. }
  22. /// returns immediate value
  23. fn get_imm(&self) -> i32 {
  24. self.get_insn().imm
  25. }
  26. /// sets destination register
  27. fn set_dst(mut self, dst: u8) -> Self {
  28. self.get_insn_mut().dst = dst;
  29. self
  30. }
  31. /// sets source register
  32. fn set_src(mut self, src: u8) -> Self {
  33. self.get_insn_mut().src = src;
  34. self
  35. }
  36. /// sets offset bytes
  37. fn set_off(mut self, offset: i16) -> Self {
  38. self.get_insn_mut().off = offset;
  39. self
  40. }
  41. /// sets immediate value
  42. fn set_imm(mut self, imm: i32) -> Self {
  43. self.get_insn_mut().imm = imm;
  44. self
  45. }
  46. /// get `ebpf::Insn` struct
  47. fn get_insn(&self) -> &Insn;
  48. /// get mutable `ebpf::Insn` struct
  49. fn get_insn_mut(&mut self) -> &mut Insn;
  50. }
  51. /// General trait for `Instruction`s and `BpfCode`.
  52. /// Provides functionality to transform `struct` into collection of bytes
  53. pub trait IntoBytes {
  54. /// type of targeted transformation
  55. type Bytes;
  56. /// consume `Self` with transformation into `Self::Bytes`
  57. fn into_bytes(self) -> Self::Bytes;
  58. }
  59. /// General implementation of `IntoBytes` for `Instruction`
  60. impl<'i, I: Instruction> IntoBytes for &'i I {
  61. type Bytes = Vec<u8>;
  62. /// transform immutable reference of `Instruction` into `Vec<u8>` with size of 8
  63. /// [ 1 byte , 1 byte , 2 bytes, 4 bytes ]
  64. /// [ OP_CODE, SRC_REG | DST_REG, OFFSET , IMMEDIATE ]
  65. fn into_bytes(self) -> Self::Bytes {
  66. let buffer = vec![
  67. self.opt_code_byte(),
  68. self.get_src() << 4 | self.get_dst(),
  69. self.get_off() as u8,
  70. (self.get_off() >> 8) as u8,
  71. self.get_imm() as u8,
  72. (self.get_imm() >> 8) as u8,
  73. (self.get_imm() >> 16) as u8,
  74. (self.get_imm() >> 24) as u8,
  75. ];
  76. buffer
  77. }
  78. }
  79. /// BPF instruction stack in byte representation
  80. #[derive(Default)]
  81. pub struct BpfCode {
  82. instructions: Vec<u8>
  83. }
  84. impl BpfCode {
  85. /// creates new empty BPF instruction stack
  86. pub fn new() -> Self {
  87. BpfCode { instructions: vec![] }
  88. }
  89. /// create ADD instruction
  90. pub fn add(&mut self, source: Source, arch: Arch) -> Move {
  91. self.mov_internal(source, arch, OpBits::Add)
  92. }
  93. /// create SUB instruction
  94. pub fn sub(&mut self, source: Source, arch: Arch) -> Move {
  95. self.mov_internal(source, arch, OpBits::Sub)
  96. }
  97. /// create MUL instruction
  98. pub fn mul(&mut self, source: Source, arch: Arch) -> Move {
  99. self.mov_internal(source, arch, OpBits::Mul)
  100. }
  101. /// create DIV instruction
  102. pub fn div(&mut self, source: Source, arch: Arch) -> Move {
  103. self.mov_internal(source, arch, OpBits::Div)
  104. }
  105. /// create OR instruction
  106. pub fn bit_or(&mut self, source: Source, arch: Arch) -> Move {
  107. self.mov_internal(source, arch, OpBits::BitOr)
  108. }
  109. /// create AND instruction
  110. pub fn bit_and(&mut self, source: Source, arch: Arch) -> Move {
  111. self.mov_internal(source, arch, OpBits::BitAnd)
  112. }
  113. /// create LSHIFT instruction
  114. pub fn left_shift(&mut self, source: Source, arch: Arch) -> Move {
  115. self.mov_internal(source, arch, OpBits::LShift)
  116. }
  117. /// create RSHIFT instruction
  118. pub fn right_shift(&mut self, source: Source, arch: Arch) -> Move {
  119. self.mov_internal(source, arch, OpBits::RShift)
  120. }
  121. /// create NEGATE instruction
  122. pub fn negate(&mut self, arch: Arch) -> Move {
  123. self.mov_internal(Source::Imm, arch, OpBits::Negate)
  124. }
  125. /// create MOD instruction
  126. pub fn modulo(&mut self, source: Source, arch: Arch) -> Move {
  127. self.mov_internal(source, arch, OpBits::Mod)
  128. }
  129. /// create XOR instruction
  130. pub fn bit_xor(&mut self, source: Source, arch: Arch) -> Move {
  131. self.mov_internal(source, arch, OpBits::BitXor)
  132. }
  133. /// create MOV instruction
  134. pub fn mov(&mut self, source: Source, arch: Arch) -> Move {
  135. self.mov_internal(source, arch, OpBits::Mov)
  136. }
  137. /// create SIGNED RSHIFT instruction
  138. pub fn signed_right_shift(&mut self, source: Source, arch: Arch) -> Move {
  139. self.mov_internal(source, arch, OpBits::SignRShift)
  140. }
  141. #[inline]
  142. fn mov_internal(&mut self, source: Source, arch_bits: Arch, op_bits: OpBits) -> Move {
  143. Move {
  144. bpf_code: self,
  145. src_bit: source,
  146. op_bits,
  147. arch_bits,
  148. insn: Insn {
  149. opc: 0x00,
  150. dst: 0x00,
  151. src: 0x00,
  152. off: 0x00_00,
  153. imm: 0x00_00_00_00
  154. }
  155. }
  156. }
  157. /// create byte swap instruction
  158. pub fn swap_bytes(&mut self, endian: Endian) -> SwapBytes {
  159. SwapBytes {
  160. bpf_code: self,
  161. endian,
  162. insn: Insn {
  163. opc: 0x00,
  164. dst: 0x00,
  165. src: 0x00,
  166. off: 0x00_00,
  167. imm: 0x00_00_00_00
  168. }
  169. }
  170. }
  171. /// create LOAD instruction, IMMEDIATE is the source
  172. pub fn load(&mut self, mem_size: MemSize) -> Load {
  173. self.load_internal(mem_size, Addressing::Imm, BPF_LD)
  174. }
  175. /// create ABSOLUTE LOAD instruction
  176. pub fn load_abs(&mut self, mem_size: MemSize) -> Load {
  177. self.load_internal(mem_size, Addressing::Abs, BPF_LD)
  178. }
  179. /// create INDIRECT LOAD instruction
  180. pub fn load_ind(&mut self, mem_size: MemSize) -> Load {
  181. self.load_internal(mem_size, Addressing::Ind, BPF_LD)
  182. }
  183. /// create LOAD instruction, MEMORY is the source
  184. pub fn load_x(&mut self, mem_size: MemSize) -> Load {
  185. self.load_internal(mem_size, Addressing::Mem, BPF_LDX)
  186. }
  187. #[inline]
  188. fn load_internal(&mut self, mem_size: MemSize, addressing: Addressing, source: u8) -> Load {
  189. Load {
  190. bpf_code: self,
  191. addressing,
  192. mem_size,
  193. source,
  194. insn: Insn {
  195. opc: 0x00,
  196. dst: 0x00,
  197. src: 0x00,
  198. off: 0x00_00,
  199. imm: 0x00_00_00_00
  200. }
  201. }
  202. }
  203. /// creates STORE instruction, IMMEDIATE is the source
  204. pub fn store(&mut self, mem_size: MemSize) -> Store {
  205. self.store_internal(mem_size, BPF_IMM)
  206. }
  207. /// creates STORE instruction, MEMORY is the source
  208. pub fn store_x(&mut self, mem_size: MemSize) -> Store {
  209. self.store_internal(mem_size, BPF_MEM | BPF_STX)
  210. }
  211. #[inline]
  212. fn store_internal(&mut self, mem_size: MemSize, source: u8) -> Store {
  213. Store {
  214. bpf_code: self,
  215. mem_size,
  216. source,
  217. insn: Insn {
  218. opc: 0x00,
  219. dst: 0x00,
  220. src: 0x00,
  221. off: 0x00_00,
  222. imm: 0x00_00_00_00
  223. }
  224. }
  225. }
  226. /// create unconditional JMP instruction
  227. pub fn jump_unconditional(&mut self) -> Jump {
  228. self.jump_conditional(Cond::Abs, Source::Imm)
  229. }
  230. /// create conditional JMP instruction
  231. pub fn jump_conditional(&mut self, cond: Cond, src_bit: Source) -> Jump {
  232. Jump {
  233. bpf_code: self,
  234. cond,
  235. src_bit,
  236. insn: Insn {
  237. opc: 0x00,
  238. dst: 0x00,
  239. src: 0x00,
  240. off: 0x00_00,
  241. imm: 0x00_00_00_00
  242. }
  243. }
  244. }
  245. /// create CALL instruction
  246. pub fn call(&mut self) -> FunctionCall {
  247. FunctionCall {
  248. bpf_code: self,
  249. insn: Insn {
  250. opc: 0x00,
  251. dst: 0x00,
  252. src: 0x00,
  253. off: 0x00_00,
  254. imm: 0x00_00_00_00
  255. }
  256. }
  257. }
  258. /// create EXIT instruction
  259. pub fn exit(&mut self) -> Exit {
  260. Exit {
  261. bpf_code: self,
  262. insn: Insn {
  263. opc: 0x00,
  264. dst: 0x00,
  265. src: 0x00,
  266. off: 0x00_00,
  267. imm: 0x00_00_00_00
  268. }
  269. }
  270. }
  271. }
  272. /// Transform `BpfCode` into assemble representation
  273. impl<'a> IntoBytes for &'a BpfCode {
  274. type Bytes = &'a [u8];
  275. /// returns `BpfCode` instruction stack as `&[u8]`
  276. fn into_bytes(self) -> Self::Bytes {
  277. self.instructions.as_slice()
  278. }
  279. }
  280. /// struct to represent `MOV ALU` instructions
  281. pub struct Move<'i> {
  282. bpf_code: &'i mut BpfCode,
  283. src_bit: Source,
  284. op_bits: OpBits,
  285. arch_bits: Arch,
  286. insn: Insn
  287. }
  288. impl<'i> Move<'i> {
  289. /// push MOV instruction into BpfCode instruction stack
  290. pub fn push(self) -> &'i mut BpfCode {
  291. let mut asm = self.into_bytes();
  292. self.bpf_code.instructions.append(&mut asm);
  293. self.bpf_code
  294. }
  295. }
  296. impl<'i> Instruction for Move<'i> {
  297. fn opt_code_byte(&self) -> u8 {
  298. let op_bits = self.op_bits as u8;
  299. let src_bit = self.src_bit as u8;
  300. let arch_bits = self.arch_bits as u8;
  301. op_bits | src_bit | arch_bits
  302. }
  303. fn get_insn_mut(&mut self) -> &mut Insn {
  304. &mut self.insn
  305. }
  306. fn get_insn(&self) -> &Insn {
  307. &self.insn
  308. }
  309. }
  310. #[derive(Copy, Clone, PartialEq, Eq)]
  311. /// The source of ALU and JMP instructions
  312. pub enum Source {
  313. /// immediate field will be used as a source
  314. Imm = BPF_IMM as isize,
  315. /// src register will be used as a source
  316. Reg = BPF_X as isize
  317. }
  318. #[derive(Copy, Clone)]
  319. enum OpBits {
  320. Add = BPF_ADD as isize,
  321. Sub = BPF_SUB as isize,
  322. Mul = BPF_MUL as isize,
  323. Div = BPF_DIV as isize,
  324. BitOr = BPF_OR as isize,
  325. BitAnd = BPF_AND as isize,
  326. LShift = BPF_LSH as isize,
  327. RShift = BPF_RSH as isize,
  328. Negate = BPF_NEG as isize,
  329. Mod = BPF_MOD as isize,
  330. BitXor = BPF_XOR as isize,
  331. Mov = BPF_MOV as isize,
  332. SignRShift = BPF_ARSH as isize
  333. }
  334. #[derive(Copy, Clone)]
  335. /// Architecture of instructions
  336. pub enum Arch {
  337. /// 64-bit instructions
  338. X64 = BPF_ALU64 as isize,
  339. /// 32-bit instructions
  340. X32 = BPF_ALU as isize
  341. }
  342. /// struct representation of byte swap operation
  343. pub struct SwapBytes<'i> {
  344. bpf_code: &'i mut BpfCode,
  345. endian: Endian,
  346. insn: Insn
  347. }
  348. impl<'i> SwapBytes<'i> {
  349. /// push bytes swap instruction into BpfCode instruction stack
  350. pub fn push(self) -> &'i mut BpfCode {
  351. let mut asm = self.into_bytes();
  352. self.bpf_code.instructions.append(&mut asm);
  353. self.bpf_code
  354. }
  355. }
  356. impl<'i> Instruction for SwapBytes<'i> {
  357. fn opt_code_byte(&self) -> u8 {
  358. self.endian as u8
  359. }
  360. fn get_insn_mut(&mut self) -> &mut Insn {
  361. &mut self.insn
  362. }
  363. fn get_insn(&self) -> &Insn {
  364. &self.insn
  365. }
  366. }
  367. #[derive(Copy, Clone)]
  368. /// Bytes endian
  369. pub enum Endian {
  370. /// Little endian
  371. Little = LE as isize,
  372. /// Big endian
  373. Big = BE as isize
  374. }
  375. /// struct representation of LOAD instructions
  376. pub struct Load<'i> {
  377. bpf_code: &'i mut BpfCode,
  378. addressing: Addressing,
  379. mem_size: MemSize,
  380. source: u8,
  381. insn: Insn
  382. }
  383. impl<'i> Load<'i> {
  384. /// push LOAD instruction into BpfCode instruction stack
  385. pub fn push(self) -> &'i mut BpfCode {
  386. let mut asm = self.into_bytes();
  387. self.bpf_code.instructions.append(&mut asm);
  388. self.bpf_code
  389. }
  390. }
  391. impl<'i> Instruction for Load<'i> {
  392. fn opt_code_byte(&self) -> u8 {
  393. let size = self.mem_size as u8;
  394. let addressing = self.addressing as u8;
  395. addressing | size | self.source
  396. }
  397. fn get_insn_mut(&mut self) -> &mut Insn {
  398. &mut self.insn
  399. }
  400. fn get_insn(&self) -> &Insn {
  401. &self.insn
  402. }
  403. }
  404. /// struct representation of STORE instructions
  405. pub struct Store<'i> {
  406. bpf_code: &'i mut BpfCode,
  407. mem_size: MemSize,
  408. source: u8,
  409. insn: Insn
  410. }
  411. impl<'i> Store<'i> {
  412. /// push STORE instruction into BpfCode instruction stack
  413. pub fn push(self) -> &'i mut BpfCode {
  414. let mut asm = self.into_bytes();
  415. self.bpf_code.instructions.append(&mut asm);
  416. self.bpf_code
  417. }
  418. }
  419. impl<'i> Instruction for Store<'i> {
  420. fn opt_code_byte(&self) -> u8 {
  421. let size = self.mem_size as u8;
  422. BPF_MEM | BPF_ST | size | self.source
  423. }
  424. fn get_insn_mut(&mut self) -> &mut Insn {
  425. &mut self.insn
  426. }
  427. fn get_insn(&self) -> &Insn {
  428. &self.insn
  429. }
  430. }
  431. #[derive(Copy, Clone)]
  432. /// Memory size for LOAD and STORE instructions
  433. pub enum MemSize {
  434. /// 8-bit size
  435. Byte = BPF_B as isize,
  436. /// 16-bit size
  437. HalfWord = BPF_H as isize,
  438. /// 32-bit size
  439. Word = BPF_W as isize,
  440. /// 64-bit size
  441. DoubleWord = BPF_DW as isize
  442. }
  443. #[derive(Copy, Clone)]
  444. enum Addressing {
  445. Imm = BPF_IMM as isize,
  446. Abs = BPF_ABS as isize,
  447. Ind = BPF_IND as isize,
  448. Mem = BPF_MEM as isize
  449. }
  450. /// struct representation of JMP instructions
  451. pub struct Jump<'i> {
  452. bpf_code: &'i mut BpfCode,
  453. cond: Cond,
  454. src_bit: Source,
  455. insn: Insn
  456. }
  457. impl<'i> Jump<'i> {
  458. /// push JMP instruction into BpfCode instruction stack
  459. pub fn push(self) -> &'i mut BpfCode {
  460. let mut asm = self.into_bytes();
  461. self.bpf_code.instructions.append(&mut asm);
  462. self.bpf_code
  463. }
  464. }
  465. impl<'i> Instruction for Jump<'i> {
  466. fn opt_code_byte(&self) -> u8 {
  467. let cmp: u8 = self.cond as u8;
  468. let src_bit = self.src_bit as u8;
  469. cmp | src_bit | BPF_JMP
  470. }
  471. fn get_insn_mut(&mut self) -> &mut Insn {
  472. &mut self.insn
  473. }
  474. fn get_insn(&self) -> &Insn {
  475. &self.insn
  476. }
  477. }
  478. #[derive(Copy, Clone, PartialEq, Eq)]
  479. /// Conditions for JMP instructions
  480. pub enum Cond {
  481. /// Absolute or unconditional
  482. Abs = BPF_JA as isize,
  483. /// Jump if `==`
  484. Equals = BPF_JEQ as isize,
  485. /// Jump if `>`
  486. Greater = BPF_JGT as isize,
  487. /// Jump if `>=`
  488. GreaterEquals = BPF_JGE as isize,
  489. /// Jump if `<`
  490. Lower = BPF_JLT as isize,
  491. /// Jump if `<=`
  492. LowerEquals = BPF_JLE as isize,
  493. /// Jump if `src` & `dst`
  494. BitAnd = BPF_JSET as isize,
  495. /// Jump if `!=`
  496. NotEquals = BPF_JNE as isize,
  497. /// Jump if `>` (signed)
  498. GreaterSigned = BPF_JSGT as isize,
  499. /// Jump if `>=` (signed)
  500. GreaterEqualsSigned = BPF_JSGE as isize,
  501. /// Jump if `<` (signed)
  502. LowerSigned = BPF_JSLT as isize,
  503. /// Jump if `<=` (signed)
  504. LowerEqualsSigned = BPF_JSLE as isize
  505. }
  506. /// struct representation of CALL instruction
  507. pub struct FunctionCall<'i> {
  508. bpf_code: &'i mut BpfCode,
  509. insn: Insn
  510. }
  511. impl<'i> FunctionCall<'i> {
  512. /// push CALL instruction into BpfCode instruction stack
  513. pub fn push(self) -> &'i mut BpfCode {
  514. let mut asm = self.into_bytes();
  515. self.bpf_code.instructions.append(&mut asm);
  516. self.bpf_code
  517. }
  518. }
  519. impl<'i> Instruction for FunctionCall<'i> {
  520. fn opt_code_byte(&self) -> u8 {
  521. BPF_CALL | BPF_JMP
  522. }
  523. fn get_insn_mut(&mut self) -> &mut Insn {
  524. &mut self.insn
  525. }
  526. fn get_insn(&self) -> &Insn {
  527. &self.insn
  528. }
  529. }
  530. /// struct representation of EXIT instruction
  531. pub struct Exit<'i> {
  532. bpf_code: &'i mut BpfCode,
  533. insn: Insn
  534. }
  535. impl<'i> Exit<'i> {
  536. /// push EXIT instruction into BpfCode instruction stack
  537. pub fn push(self) -> &'i mut BpfCode {
  538. let mut asm = self.into_bytes();
  539. self.bpf_code.instructions.append(&mut asm);
  540. self.bpf_code
  541. }
  542. }
  543. impl<'i> Instruction for Exit<'i> {
  544. fn opt_code_byte(&self) -> u8 {
  545. BPF_EXIT | BPF_JMP
  546. }
  547. fn get_insn_mut(&mut self) -> &mut Insn {
  548. &mut self.insn
  549. }
  550. fn get_insn(&self) -> &Insn {
  551. &self.insn
  552. }
  553. }
  554. #[cfg(test)]
  555. mod tests {
  556. #[cfg(test)]
  557. mod special {
  558. use super::super::*;
  559. #[test]
  560. fn call_immediate() {
  561. let mut program = BpfCode::new();
  562. program.call().set_imm(0x11_22_33_44).push();
  563. assert_eq!(program.into_bytes(), &[0x85, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]);
  564. }
  565. #[test]
  566. fn exit_operation() {
  567. let mut program = BpfCode::new();
  568. program.exit().push();
  569. assert_eq!(program.into_bytes(), &[0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  570. }
  571. }
  572. #[cfg(test)]
  573. mod jump_instructions {
  574. #[cfg(test)]
  575. mod register {
  576. use super::super::super::*;
  577. #[test]
  578. fn jump_on_dst_equals_src() {
  579. let mut program = BpfCode::new();
  580. program.jump_conditional(Cond::Equals, Source::Reg).set_dst(0x01).set_src(0x02).push();
  581. assert_eq!(program.into_bytes(), &[0x1d, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  582. }
  583. #[test]
  584. fn jump_on_dst_greater_than_src() {
  585. let mut program = BpfCode::new();
  586. program.jump_conditional(Cond::Greater, Source::Reg).set_dst(0x03).set_src(0x02).push();
  587. assert_eq!(program.into_bytes(), &[0x2d, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  588. }
  589. #[test]
  590. fn jump_on_dst_greater_or_equals_to_src() {
  591. let mut program = BpfCode::new();
  592. program.jump_conditional(Cond::GreaterEquals, Source::Reg).set_dst(0x04).set_src(0x01).push();
  593. assert_eq!(program.into_bytes(), &[0x3d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  594. }
  595. #[test]
  596. fn jump_on_dst_lower_than_src() {
  597. let mut program = BpfCode::new();
  598. program.jump_conditional(Cond::Lower, Source::Reg).set_dst(0x03).set_src(0x02).push();
  599. assert_eq!(program.into_bytes(), &[0xad, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  600. }
  601. #[test]
  602. fn jump_on_dst_lower_or_equals_to_src() {
  603. let mut program = BpfCode::new();
  604. program.jump_conditional(Cond::LowerEquals, Source::Reg).set_dst(0x04).set_src(0x01).push();
  605. assert_eq!(program.into_bytes(), &[0xbd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  606. }
  607. #[test]
  608. fn jump_on_dst_bit_and_with_src_not_equal_zero() {
  609. let mut program = BpfCode::new();
  610. program.jump_conditional(Cond::BitAnd, Source::Reg).set_dst(0x05).set_src(0x02).push();
  611. assert_eq!(program.into_bytes(), &[0x4d, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  612. }
  613. #[test]
  614. fn jump_on_dst_not_equals_src() {
  615. let mut program = BpfCode::new();
  616. program.jump_conditional(Cond::NotEquals, Source::Reg).set_dst(0x03).set_src(0x05).push();
  617. assert_eq!(program.into_bytes(), &[0x5d, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  618. }
  619. #[test]
  620. fn jump_on_dst_greater_than_src_signed() {
  621. let mut program = BpfCode::new();
  622. program.jump_conditional(Cond::GreaterSigned, Source::Reg).set_dst(0x04).set_src(0x01).push();
  623. assert_eq!(program.into_bytes(), &[0x6d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  624. }
  625. #[test]
  626. fn jump_on_dst_greater_or_equals_src_signed() {
  627. let mut program = BpfCode::new();
  628. program.jump_conditional(Cond::GreaterEqualsSigned, Source::Reg).set_dst(0x01).set_src(0x03).push();
  629. assert_eq!(program.into_bytes(), &[0x7d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  630. }
  631. #[test]
  632. fn jump_on_dst_lower_than_src_signed() {
  633. let mut program = BpfCode::new();
  634. program.jump_conditional(Cond::LowerSigned, Source::Reg).set_dst(0x04).set_src(0x01).push();
  635. assert_eq!(program.into_bytes(), &[0xcd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  636. }
  637. #[test]
  638. fn jump_on_dst_lower_or_equals_src_signed() {
  639. let mut program = BpfCode::new();
  640. program.jump_conditional(Cond::LowerEqualsSigned, Source::Reg).set_dst(0x01).set_src(0x03).push();
  641. assert_eq!(program.into_bytes(), &[0xdd, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  642. }
  643. }
  644. #[cfg(test)]
  645. mod immediate {
  646. use super::super::super::*;
  647. #[test]
  648. fn jump_to_label() {
  649. let mut program = BpfCode::new();
  650. program.jump_unconditional().set_off(0x00_11).push();
  651. assert_eq!(program.into_bytes(), &[0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
  652. }
  653. #[test]
  654. fn jump_on_dst_equals_const() {
  655. let mut program = BpfCode::new();
  656. program.jump_conditional(Cond::Equals, Source::Imm).set_dst(0x01).set_imm(0x00_11_22_33).push();
  657. assert_eq!(program.into_bytes(), &[0x15, 0x01, 0x00, 0x00, 0x33, 0x22, 0x11, 0x00]);
  658. }
  659. #[test]
  660. fn jump_on_dst_greater_than_const() {
  661. let mut program = BpfCode::new();
  662. program.jump_conditional(Cond::Greater, Source::Imm).set_dst(0x02).set_imm(0x00_11_00_11).push();
  663. assert_eq!(program.into_bytes(), &[0x25, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]);
  664. }
  665. #[test]
  666. fn jump_on_dst_greater_or_equals_to_const() {
  667. let mut program = BpfCode::new();
  668. program.jump_conditional(Cond::GreaterEquals, Source::Imm).set_dst(0x04).set_imm(0x00_22_11_00).push();
  669. assert_eq!(program.into_bytes(), &[0x35, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]);
  670. }
  671. #[test]
  672. fn jump_on_dst_lower_than_const() {
  673. let mut program = BpfCode::new();
  674. program.jump_conditional(Cond::Lower, Source::Imm).set_dst(0x02).set_imm(0x00_11_00_11).push();
  675. assert_eq!(program.into_bytes(), &[0xa5, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]);
  676. }
  677. #[test]
  678. fn jump_on_dst_lower_or_equals_to_const() {
  679. let mut program = BpfCode::new();
  680. program.jump_conditional(Cond::LowerEquals, Source::Imm).set_dst(0x04).set_imm(0x00_22_11_00).push();
  681. assert_eq!(program.into_bytes(), &[0xb5, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]);
  682. }
  683. #[test]
  684. fn jump_on_dst_bit_and_with_const_not_equal_zero() {
  685. let mut program = BpfCode::new();
  686. program.jump_conditional(Cond::BitAnd, Source::Imm).set_dst(0x05).push();
  687. assert_eq!(program.into_bytes(), &[0x45, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  688. }
  689. #[test]
  690. fn jump_on_dst_not_equals_const() {
  691. let mut program = BpfCode::new();
  692. program.jump_conditional(Cond::NotEquals, Source::Imm).set_dst(0x03).push();
  693. assert_eq!(program.into_bytes(), &[0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  694. }
  695. #[test]
  696. fn jump_on_dst_greater_than_const_signed() {
  697. let mut program = BpfCode::new();
  698. program.jump_conditional(Cond::GreaterSigned, Source::Imm).set_dst(0x04).push();
  699. assert_eq!(program.into_bytes(), &[0x65, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  700. }
  701. #[test]
  702. fn jump_on_dst_greater_or_equals_src_signed() {
  703. let mut program = BpfCode::new();
  704. program.jump_conditional(Cond::GreaterEqualsSigned, Source::Imm).set_dst(0x01).push();
  705. assert_eq!(program.into_bytes(), &[0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  706. }
  707. #[test]
  708. fn jump_on_dst_lower_than_const_signed() {
  709. let mut program = BpfCode::new();
  710. program.jump_conditional(Cond::LowerSigned, Source::Imm).set_dst(0x04).push();
  711. assert_eq!(program.into_bytes(), &[0xc5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  712. }
  713. #[test]
  714. fn jump_on_dst_lower_or_equals_src_signed() {
  715. let mut program = BpfCode::new();
  716. program.jump_conditional(Cond::LowerEqualsSigned, Source::Imm).set_dst(0x01).push();
  717. assert_eq!(program.into_bytes(), &[0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  718. }
  719. }
  720. }
  721. #[cfg(test)]
  722. mod store_instructions {
  723. use super::super::*;
  724. #[test]
  725. fn store_word_from_dst_into_immediate_address() {
  726. let mut program = BpfCode::new();
  727. program.store(MemSize::Word).set_dst(0x01).set_off(0x00_11).set_imm(0x11_22_33_44).push();
  728. assert_eq!(program.into_bytes(), &[0x62, 0x01, 0x11, 0x00, 0x44, 0x33, 0x22, 0x11]);
  729. }
  730. #[test]
  731. fn store_half_word_from_dst_into_immediate_address() {
  732. let mut program = BpfCode::new();
  733. program.store(MemSize::HalfWord).set_dst(0x02).set_off(0x11_22).push();
  734. assert_eq!(program.into_bytes(), &[0x6a, 0x02, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]);
  735. }
  736. #[test]
  737. fn store_byte_from_dst_into_immediate_address() {
  738. let mut program = BpfCode::new();
  739. program.store(MemSize::Byte).push();
  740. assert_eq!(program.into_bytes(), &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  741. }
  742. #[test]
  743. fn store_double_word_from_dst_into_immediate_address() {
  744. let mut program = BpfCode::new();
  745. program.store(MemSize::DoubleWord).push();
  746. assert_eq!(program.into_bytes(), &[0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  747. }
  748. #[test]
  749. fn store_word_from_dst_into_src_address() {
  750. let mut program = BpfCode::new();
  751. program.store_x(MemSize::Word).set_dst(0x01).set_src(0x02).push();
  752. assert_eq!(program.into_bytes(), &[0x63, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  753. }
  754. #[test]
  755. fn store_half_word_from_dst_into_src_address() {
  756. let mut program = BpfCode::new();
  757. program.store_x(MemSize::HalfWord).push();
  758. assert_eq!(program.into_bytes(), &[0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  759. }
  760. #[test]
  761. fn store_byte_from_dst_into_src_address() {
  762. let mut program = BpfCode::new();
  763. program.store_x(MemSize::Byte).push();
  764. assert_eq!(program.into_bytes(), &[0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  765. }
  766. #[test]
  767. fn store_double_word_from_dst_into_src_address() {
  768. let mut program = BpfCode::new();
  769. program.store_x(MemSize::DoubleWord).push();
  770. assert_eq!(program.into_bytes(), &[0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  771. }
  772. }
  773. #[cfg(test)]
  774. mod load_instructions {
  775. #[cfg(test)]
  776. mod register {
  777. use super::super::super::*;
  778. #[test]
  779. fn load_word_from_set_src_with_offset() {
  780. let mut program = BpfCode::new();
  781. program.load_x(MemSize::Word).set_dst(0x01).set_src(0x02).set_off(0x00_02).push();
  782. assert_eq!(program.into_bytes(), &[0x61, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00]);
  783. }
  784. #[test]
  785. fn load_half_word_from_set_src_with_offset() {
  786. let mut program = BpfCode::new();
  787. program.load_x(MemSize::HalfWord).set_dst(0x02).set_src(0x01).set_off(0x11_22).push();
  788. assert_eq!(program.into_bytes(), &[0x69, 0x12, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]);
  789. }
  790. #[test]
  791. fn load_byte_from_set_src_with_offset() {
  792. let mut program = BpfCode::new();
  793. program.load_x(MemSize::Byte).set_dst(0x01).set_src(0x04).set_off(0x00_11).push();
  794. assert_eq!(program.into_bytes(), &[0x71, 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]);
  795. }
  796. #[test]
  797. fn load_double_word_from_set_src_with_offset() {
  798. let mut program = BpfCode::new();
  799. program.load_x(MemSize::DoubleWord).set_dst(0x04).set_src(0x05).set_off(0x44_55).push();
  800. assert_eq!(program.into_bytes(), &[0x79, 0x54, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00]);
  801. }
  802. }
  803. #[cfg(test)]
  804. mod immediate {
  805. use super::super::super::*;
  806. #[test]
  807. fn load_double_word() {
  808. let mut program = BpfCode::new();
  809. program.load(MemSize::DoubleWord).set_dst(0x01).set_imm(0x00_01_02_03).push();
  810. assert_eq!(program.into_bytes(), &[0x18, 0x01, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]);
  811. }
  812. #[test]
  813. fn load_abs_word() {
  814. let mut program = BpfCode::new();
  815. program.load_abs(MemSize::Word).push();
  816. assert_eq!(program.into_bytes(), &[0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  817. }
  818. #[test]
  819. fn load_abs_half_word() {
  820. let mut program = BpfCode::new();
  821. program.load_abs(MemSize::HalfWord).set_dst(0x05).push();
  822. assert_eq!(program.into_bytes(), &[0x28, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  823. }
  824. #[test]
  825. fn load_abs_byte() {
  826. let mut program = BpfCode::new();
  827. program.load_abs(MemSize::Byte).set_dst(0x01).push();
  828. assert_eq!(program.into_bytes(), &[0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  829. }
  830. #[test]
  831. fn load_abs_double_word() {
  832. let mut program = BpfCode::new();
  833. program.load_abs(MemSize::DoubleWord).set_dst(0x01).set_imm(0x01_02_03_04).push();
  834. assert_eq!(program.into_bytes(), &[0x38, 0x01, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]);
  835. }
  836. #[test]
  837. fn load_indirect_word() {
  838. let mut program = BpfCode::new();
  839. program.load_ind(MemSize::Word).push();
  840. assert_eq!(program.into_bytes(), &[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  841. }
  842. #[test]
  843. fn load_indirect_half_word() {
  844. let mut program = BpfCode::new();
  845. program.load_ind(MemSize::HalfWord).push();
  846. assert_eq!(program.into_bytes(), &[0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  847. }
  848. #[test]
  849. fn load_indirect_byte() {
  850. let mut program = BpfCode::new();
  851. program.load_ind(MemSize::Byte).push();
  852. assert_eq!(program.into_bytes(), &[0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  853. }
  854. #[test]
  855. fn load_indirect_double_word() {
  856. let mut program = BpfCode::new();
  857. program.load_ind(MemSize::DoubleWord).push();
  858. assert_eq!(program.into_bytes(), &[0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  859. }
  860. }
  861. }
  862. #[cfg(test)]
  863. mod byte_swap_instructions {
  864. use super::super::*;
  865. #[test]
  866. fn convert_host_to_little_endian_16bits() {
  867. let mut program = BpfCode::new();
  868. program.swap_bytes(Endian::Little).set_dst(0x01).set_imm(0x00_00_00_10).push();
  869. assert_eq!(program.into_bytes(), &[0xd4, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]);
  870. }
  871. #[test]
  872. fn convert_host_to_little_endian_32bits() {
  873. let mut program = BpfCode::new();
  874. program.swap_bytes(Endian::Little).set_dst(0x02).set_imm(0x00_00_00_20).push();
  875. assert_eq!(program.into_bytes(), &[0xd4, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]);
  876. }
  877. #[test]
  878. fn convert_host_to_little_endian_64bit() {
  879. let mut program = BpfCode::new();
  880. program.swap_bytes(Endian::Little).set_dst(0x03).set_imm(0x00_00_00_40).push();
  881. assert_eq!(program.into_bytes(), &[0xd4, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]);
  882. }
  883. #[test]
  884. fn convert_host_to_big_endian_16bits() {
  885. let mut program = BpfCode::new();
  886. program.swap_bytes(Endian::Big).set_dst(0x01).set_imm(0x00_00_00_10).push();
  887. assert_eq!(program.into_bytes(), &[0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]);
  888. }
  889. #[test]
  890. fn convert_host_to_big_endian_32bits() {
  891. let mut program = BpfCode::new();
  892. program.swap_bytes(Endian::Big).set_dst(0x02).set_imm(0x00_00_00_20).push();
  893. assert_eq!(program.into_bytes(), &[0xdc, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]);
  894. }
  895. #[test]
  896. fn convert_host_to_big_endian_64bit() {
  897. let mut program = BpfCode::new();
  898. program.swap_bytes(Endian::Big).set_dst(0x03).set_imm(0x00_00_00_40).push();
  899. assert_eq!(program.into_bytes(), &[0xdc, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]);
  900. }
  901. }
  902. #[cfg(test)]
  903. mod moves_instructions {
  904. #[cfg(test)]
  905. mod arch_x64 {
  906. #[cfg(test)]
  907. mod immediate {
  908. use super::super::super::super::*;
  909. #[test]
  910. fn move_and_add_const_to_register() {
  911. let mut program = BpfCode::new();
  912. program.add(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x01_02_03_04).push();
  913. assert_eq!(program.into_bytes(), &[0x07, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]);
  914. }
  915. #[test]
  916. fn move_sub_const_to_register() {
  917. let mut program = BpfCode::new();
  918. program.sub(Source::Imm, Arch::X64).set_dst(0x04).set_imm(0x00_01_02_03).push();
  919. assert_eq!(program.into_bytes(), &[0x17, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]);
  920. }
  921. #[test]
  922. fn move_mul_const_to_register() {
  923. let mut program = BpfCode::new();
  924. program.mul(Source::Imm, Arch::X64).set_dst(0x05).set_imm(0x04_03_02_01).push();
  925. assert_eq!(program.into_bytes(), &[0x27, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]);
  926. }
  927. #[test]
  928. fn move_div_constant_to_register() {
  929. let mut program = BpfCode::new();
  930. program.div(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x00_ff_00_ff).push();
  931. assert_eq!(program.into_bytes(), &[0x37, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]);
  932. }
  933. #[test]
  934. fn move_bit_or_const_to_register() {
  935. let mut program = BpfCode::new();
  936. program.bit_or(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x00_11_00_22).push();
  937. assert_eq!(program.into_bytes(), &[0x47, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]);
  938. }
  939. #[test]
  940. fn move_bit_and_const_to_register() {
  941. let mut program = BpfCode::new();
  942. program.bit_and(Source::Imm, Arch::X64).set_dst(0x02).set_imm(0x11_22_33_44).push();
  943. assert_eq!(program.into_bytes(), &[0x57, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]);
  944. }
  945. #[test]
  946. fn move_left_shift_const_to_register() {
  947. let mut program = BpfCode::new();
  948. program.left_shift(Source::Imm, Arch::X64).set_dst(0x01).push();
  949. assert_eq!(program.into_bytes(), &[0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  950. }
  951. #[test]
  952. fn move_logical_right_shift_const_to_register() {
  953. let mut program = BpfCode::new();
  954. program.right_shift(Source::Imm, Arch::X64).set_dst(0x01).push();
  955. assert_eq!(program.into_bytes(), &[0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  956. }
  957. #[test]
  958. fn move_negate_register() {
  959. let mut program = BpfCode::new();
  960. program.negate(Arch::X64).set_dst(0x02).push();
  961. assert_eq!(program.into_bytes(), &[0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  962. }
  963. #[test]
  964. fn move_mod_const_to_register() {
  965. let mut program = BpfCode::new();
  966. program.modulo(Source::Imm, Arch::X64).set_dst(0x02).push();
  967. assert_eq!(program.into_bytes(), &[0x97, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  968. }
  969. #[test]
  970. fn move_bit_xor_const_to_register() {
  971. let mut program = BpfCode::new();
  972. program.bit_xor(Source::Imm, Arch::X64).set_dst(0x03).push();
  973. assert_eq!(program.into_bytes(), &[0xa7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  974. }
  975. #[test]
  976. fn move_const_to_register() {
  977. let mut program = BpfCode::new();
  978. program.mov(Source::Imm, Arch::X64).set_dst(0x01).set_imm(0x00_00_00_FF).push();
  979. assert_eq!(program.into_bytes(), &[0xb7, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]);
  980. }
  981. #[test]
  982. fn move_signed_right_shift_const_to_register() {
  983. let mut program = BpfCode::new();
  984. program.signed_right_shift(Source::Imm, Arch::X64).set_dst(0x05).push();
  985. assert_eq!(program.into_bytes(), &[0xc7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  986. }
  987. }
  988. #[cfg(test)]
  989. mod register {
  990. use super::super::super::super::*;
  991. #[test]
  992. fn move_and_add_from_register() {
  993. let mut program = BpfCode::new();
  994. program.add(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x02).push();
  995. assert_eq!(program.into_bytes(), &[0x0f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  996. }
  997. #[test]
  998. fn move_sub_from_register_to_register() {
  999. let mut program = BpfCode::new();
  1000. program.sub(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x04).push();
  1001. assert_eq!(program.into_bytes(), &[0x1f, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1002. }
  1003. #[test]
  1004. fn move_mul_from_register_to_register() {
  1005. let mut program = BpfCode::new();
  1006. program.mul(Source::Reg, Arch::X64).set_dst(0x04).set_src(0x03).push();
  1007. assert_eq!(program.into_bytes(), &[0x2f, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1008. }
  1009. #[test]
  1010. fn move_div_from_register_to_register() {
  1011. let mut program = BpfCode::new();
  1012. program.div(Source::Reg, Arch::X64).set_dst(0x01).set_src(0x00).push();
  1013. assert_eq!(program.into_bytes(), &[0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1014. }
  1015. #[test]
  1016. fn move_bit_or_from_register_to_register() {
  1017. let mut program = BpfCode::new();
  1018. program.bit_or(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x01).push();
  1019. assert_eq!(program.into_bytes(), &[0x4f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1020. }
  1021. #[test]
  1022. fn move_bit_and_from_register_to_register() {
  1023. let mut program = BpfCode::new();
  1024. program.bit_and(Source::Reg, Arch::X64).set_dst(0x03).set_src(0x02).push();
  1025. assert_eq!(program.into_bytes(), &[0x5f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1026. }
  1027. #[test]
  1028. fn move_left_shift_from_register_to_register() {
  1029. let mut program = BpfCode::new();
  1030. program.left_shift(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x03).push();
  1031. assert_eq!(program.into_bytes(), &[0x6f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1032. }
  1033. #[test]
  1034. fn move_logical_right_shift_from_register_to_register() {
  1035. let mut program = BpfCode::new();
  1036. program.right_shift(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x04).push();
  1037. assert_eq!(program.into_bytes(), &[0x7f, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1038. }
  1039. #[test]
  1040. fn move_mod_from_register_to_register() {
  1041. let mut program = BpfCode::new();
  1042. program.modulo(Source::Reg, Arch::X64).set_dst(0x01).set_src(0x02).push();
  1043. assert_eq!(program.into_bytes(), &[0x9f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1044. }
  1045. #[test]
  1046. fn move_bit_xor_from_register_to_register() {
  1047. let mut program = BpfCode::new();
  1048. program.bit_xor(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x04).push();
  1049. assert_eq!(program.into_bytes(), &[0xaf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1050. }
  1051. #[test]
  1052. fn move_from_register_to_another_register() {
  1053. let mut program = BpfCode::new();
  1054. program.mov(Source::Reg, Arch::X64).set_src(0x01).push();
  1055. assert_eq!(program.into_bytes(), &[0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1056. }
  1057. #[test]
  1058. fn move_signed_right_shift_from_register_to_register() {
  1059. let mut program = BpfCode::new();
  1060. program.signed_right_shift(Source::Reg, Arch::X64).set_dst(0x02).set_src(0x03).push();
  1061. assert_eq!(program.into_bytes(), &[0xcf, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1062. }
  1063. }
  1064. }
  1065. #[cfg(test)]
  1066. mod arch_x32 {
  1067. #[cfg(test)]
  1068. mod immediate {
  1069. use super::super::super::super::*;
  1070. #[test]
  1071. fn move_and_add_const_to_register() {
  1072. let mut program = BpfCode::new();
  1073. program.add(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x01_02_03_04).push();
  1074. assert_eq!(program.into_bytes(), &[0x04, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]);
  1075. }
  1076. #[test]
  1077. fn move_sub_const_to_register() {
  1078. let mut program = BpfCode::new();
  1079. program.sub(Source::Imm, Arch::X32).set_dst(0x04).set_imm(0x00_01_02_03).push();
  1080. assert_eq!(program.into_bytes(), &[0x14, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]);
  1081. }
  1082. #[test]
  1083. fn move_mul_const_to_register() {
  1084. let mut program = BpfCode::new();
  1085. program.mul(Source::Imm, Arch::X32).set_dst(0x05).set_imm(0x04_03_02_01).push();
  1086. assert_eq!(program.into_bytes(), &[0x24, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]);
  1087. }
  1088. #[test]
  1089. fn move_div_constant_to_register() {
  1090. let mut program = BpfCode::new();
  1091. program.div(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x00_ff_00_ff).push();
  1092. assert_eq!(program.into_bytes(), &[0x34, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]);
  1093. }
  1094. #[test]
  1095. fn move_bit_or_const_to_register() {
  1096. let mut program = BpfCode::new();
  1097. program.bit_or(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x00_11_00_22).push();
  1098. assert_eq!(program.into_bytes(), &[0x44, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]);
  1099. }
  1100. #[test]
  1101. fn move_bit_and_const_to_register() {
  1102. let mut program = BpfCode::new();
  1103. program.bit_and(Source::Imm, Arch::X32).set_dst(0x02).set_imm(0x11_22_33_44).push();
  1104. assert_eq!(program.into_bytes(), &[0x54, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]);
  1105. }
  1106. #[test]
  1107. fn move_left_shift_const_to_register() {
  1108. let mut program = BpfCode::new();
  1109. program.left_shift(Source::Imm, Arch::X32).set_dst(0x01).push();
  1110. assert_eq!(program.into_bytes(), &[0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1111. }
  1112. #[test]
  1113. fn move_logical_right_shift_const_to_register() {
  1114. let mut program = BpfCode::new();
  1115. program.right_shift(Source::Imm, Arch::X32).set_dst(0x01).push();
  1116. assert_eq!(program.into_bytes(), &[0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1117. }
  1118. #[test]
  1119. fn move_negate_register() {
  1120. let mut program = BpfCode::new();
  1121. program.negate(Arch::X32).set_dst(0x02).push();
  1122. assert_eq!(program.into_bytes(), &[0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1123. }
  1124. #[test]
  1125. fn move_mod_const_to_register() {
  1126. let mut program = BpfCode::new();
  1127. program.modulo(Source::Imm, Arch::X32).set_dst(0x02).push();
  1128. assert_eq!(program.into_bytes(), &[0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1129. }
  1130. #[test]
  1131. fn move_bit_xor_const_to_register() {
  1132. let mut program = BpfCode::new();
  1133. program.bit_xor(Source::Imm, Arch::X32).set_dst(0x03).push();
  1134. assert_eq!(program.into_bytes(), &[0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1135. }
  1136. #[test]
  1137. fn move_const_to_register() {
  1138. let mut program = BpfCode::new();
  1139. program.mov(Source::Imm, Arch::X32).set_dst(0x01).set_imm(0x00_00_00_FF).push();
  1140. assert_eq!(program.into_bytes(), &[0xb4, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]);
  1141. }
  1142. #[test]
  1143. fn move_signed_right_shift_const_to_register() {
  1144. let mut program = BpfCode::new();
  1145. program.signed_right_shift(Source::Imm, Arch::X32).set_dst(0x05).push();
  1146. assert_eq!(program.into_bytes(), &[0xc4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1147. }
  1148. }
  1149. #[cfg(test)]
  1150. mod register {
  1151. use super::super::super::super::*;
  1152. #[test]
  1153. fn move_and_add_from_register() {
  1154. let mut program = BpfCode::new();
  1155. program.add(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x02).push();
  1156. assert_eq!(program.into_bytes(), &[0x0c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1157. }
  1158. #[test]
  1159. fn move_sub_from_register_to_register() {
  1160. let mut program = BpfCode::new();
  1161. program.sub(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x04).push();
  1162. assert_eq!(program.into_bytes(), &[0x1c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1163. }
  1164. #[test]
  1165. fn move_mul_from_register_to_register() {
  1166. let mut program = BpfCode::new();
  1167. program.mul(Source::Reg, Arch::X32).set_dst(0x04).set_src(0x03).push();
  1168. assert_eq!(program.into_bytes(), &[0x2c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1169. }
  1170. #[test]
  1171. fn move_div_from_register_to_register() {
  1172. let mut program = BpfCode::new();
  1173. program.div(Source::Reg, Arch::X32).set_dst(0x01).set_src(0x00).push();
  1174. assert_eq!(program.into_bytes(), &[0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1175. }
  1176. #[test]
  1177. fn move_bit_or_from_register_to_register() {
  1178. let mut program = BpfCode::new();
  1179. program.bit_or(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x01).push();
  1180. assert_eq!(program.into_bytes(), &[0x4c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1181. }
  1182. #[test]
  1183. fn move_bit_and_from_register_to_register() {
  1184. let mut program = BpfCode::new();
  1185. program.bit_and(Source::Reg, Arch::X32).set_dst(0x03).set_src(0x02).push();
  1186. assert_eq!(program.into_bytes(), &[0x5c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1187. }
  1188. #[test]
  1189. fn move_left_shift_from_register_to_register() {
  1190. let mut program = BpfCode::new();
  1191. program.left_shift(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x03).push();
  1192. assert_eq!(program.into_bytes(), &[0x6c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1193. }
  1194. #[test]
  1195. fn move_logical_right_shift_from_register_to_register() {
  1196. let mut program = BpfCode::new();
  1197. program.right_shift(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x04).push();
  1198. assert_eq!(program.into_bytes(), &[0x7c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1199. }
  1200. #[test]
  1201. fn move_mod_from_register_to_register() {
  1202. let mut program = BpfCode::new();
  1203. program.modulo(Source::Reg, Arch::X32).set_dst(0x01).set_src(0x02).push();
  1204. assert_eq!(program.into_bytes(), &[0x9c, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1205. }
  1206. #[test]
  1207. fn move_bit_xor_from_register_to_register() {
  1208. let mut program = BpfCode::new();
  1209. program.bit_xor(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x04).push();
  1210. assert_eq!(program.into_bytes(), &[0xac, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1211. }
  1212. #[test]
  1213. fn move_from_register_to_another_register() {
  1214. let mut program = BpfCode::new();
  1215. program.mov(Source::Reg, Arch::X32).set_dst(0x00).set_src(0x01).push();
  1216. assert_eq!(program.into_bytes(), &[0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1217. }
  1218. #[test]
  1219. fn move_signed_right_shift_from_register_to_register() {
  1220. let mut program = BpfCode::new();
  1221. program.signed_right_shift(Source::Reg, Arch::X32).set_dst(0x02).set_src(0x03).push();
  1222. assert_eq!(program.into_bytes(), &[0xcc, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  1223. }
  1224. }
  1225. }
  1226. }
  1227. #[cfg(test)]
  1228. mod programs {
  1229. use super::super::*;
  1230. #[test]
  1231. fn example_from_assembler() {
  1232. let mut program = BpfCode::new();
  1233. program.add(Source::Imm, Arch::X64).set_dst(1).set_imm(0x605).push()
  1234. .mov(Source::Imm, Arch::X64).set_dst(2).set_imm(0x32).push()
  1235. .mov(Source::Reg, Arch::X64).set_src(0).set_dst(1).push()
  1236. .swap_bytes(Endian::Big).set_dst(0).set_imm(0x10).push()
  1237. .negate(Arch::X64).set_dst(2).push()
  1238. .exit().push();
  1239. let bytecode = program.into_bytes();
  1240. let ref_prog = &[
  1241. 0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00,
  1242. 0xb7, 0x02, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
  1243. 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1244. 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  1245. 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1246. 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  1247. ];
  1248. // cargo says: "`[{integer}; 48]` cannot be formatted using `{:?}`
  1249. // because it doesn't implement `std::fmt::Debug`"
  1250. // So let's check in two steps.
  1251. assert_eq!(bytecode[..32], ref_prog[..32]);
  1252. assert_eq!(bytecode[33..], ref_prog[33..]);
  1253. }
  1254. }
  1255. }