insn_builder.rs 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199
  1. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
  2. // Copyright 2017 Alex Dukhno <[email protected]>
  3. //! Module provides API to create eBPF programs by Rust programming language
  4. use alloc::{vec, vec::Vec};
  5. use crate::ebpf::*;
  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: Instruction> IntoBytes for &'_ 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 {
  88. instructions: vec![],
  89. }
  90. }
  91. /// create ADD instruction
  92. pub fn add(&mut self, source: Source, arch: Arch) -> Move {
  93. self.mov_internal(source, arch, OpBits::Add)
  94. }
  95. /// create SUB instruction
  96. pub fn sub(&mut self, source: Source, arch: Arch) -> Move {
  97. self.mov_internal(source, arch, OpBits::Sub)
  98. }
  99. /// create MUL instruction
  100. pub fn mul(&mut self, source: Source, arch: Arch) -> Move {
  101. self.mov_internal(source, arch, OpBits::Mul)
  102. }
  103. /// create DIV instruction
  104. pub fn div(&mut self, source: Source, arch: Arch) -> Move {
  105. self.mov_internal(source, arch, OpBits::Div)
  106. }
  107. /// create OR instruction
  108. pub fn bit_or(&mut self, source: Source, arch: Arch) -> Move {
  109. self.mov_internal(source, arch, OpBits::BitOr)
  110. }
  111. /// create AND instruction
  112. pub fn bit_and(&mut self, source: Source, arch: Arch) -> Move {
  113. self.mov_internal(source, arch, OpBits::BitAnd)
  114. }
  115. /// create LSHIFT instruction
  116. pub fn left_shift(&mut self, source: Source, arch: Arch) -> Move {
  117. self.mov_internal(source, arch, OpBits::LShift)
  118. }
  119. /// create RSHIFT instruction
  120. pub fn right_shift(&mut self, source: Source, arch: Arch) -> Move {
  121. self.mov_internal(source, arch, OpBits::RShift)
  122. }
  123. /// create NEGATE instruction
  124. pub fn negate(&mut self, arch: Arch) -> Move {
  125. self.mov_internal(Source::Imm, arch, OpBits::Negate)
  126. }
  127. /// create MOD instruction
  128. pub fn modulo(&mut self, source: Source, arch: Arch) -> Move {
  129. self.mov_internal(source, arch, OpBits::Mod)
  130. }
  131. /// create XOR instruction
  132. pub fn bit_xor(&mut self, source: Source, arch: Arch) -> Move {
  133. self.mov_internal(source, arch, OpBits::BitXor)
  134. }
  135. /// create MOV instruction
  136. pub fn mov(&mut self, source: Source, arch: Arch) -> Move {
  137. self.mov_internal(source, arch, OpBits::Mov)
  138. }
  139. /// create SIGNED RSHIFT instruction
  140. pub fn signed_right_shift(&mut self, source: Source, arch: Arch) -> Move {
  141. self.mov_internal(source, arch, OpBits::SignRShift)
  142. }
  143. #[inline]
  144. fn mov_internal(&mut self, source: Source, arch_bits: Arch, op_bits: OpBits) -> Move {
  145. Move {
  146. bpf_code: self,
  147. src_bit: source,
  148. op_bits,
  149. arch_bits,
  150. insn: Insn {
  151. opc: 0x00,
  152. dst: 0x00,
  153. src: 0x00,
  154. off: 0x00_00,
  155. imm: 0x00_00_00_00,
  156. },
  157. }
  158. }
  159. /// create byte swap instruction
  160. pub fn swap_bytes(&mut self, endian: Endian) -> SwapBytes {
  161. SwapBytes {
  162. bpf_code: self,
  163. endian,
  164. insn: Insn {
  165. opc: 0x00,
  166. dst: 0x00,
  167. src: 0x00,
  168. off: 0x00_00,
  169. imm: 0x00_00_00_00,
  170. },
  171. }
  172. }
  173. /// create LOAD instruction, IMMEDIATE is the source
  174. pub fn load(&mut self, mem_size: MemSize) -> Load {
  175. self.load_internal(mem_size, Addressing::Imm, BPF_LD)
  176. }
  177. /// create ABSOLUTE LOAD instruction
  178. pub fn load_abs(&mut self, mem_size: MemSize) -> Load {
  179. self.load_internal(mem_size, Addressing::Abs, BPF_LD)
  180. }
  181. /// create INDIRECT LOAD instruction
  182. pub fn load_ind(&mut self, mem_size: MemSize) -> Load {
  183. self.load_internal(mem_size, Addressing::Ind, BPF_LD)
  184. }
  185. /// create LOAD instruction, MEMORY is the source
  186. pub fn load_x(&mut self, mem_size: MemSize) -> Load {
  187. self.load_internal(mem_size, Addressing::Mem, BPF_LDX)
  188. }
  189. #[inline]
  190. fn load_internal(&mut self, mem_size: MemSize, addressing: Addressing, source: u8) -> Load {
  191. Load {
  192. bpf_code: self,
  193. addressing,
  194. mem_size,
  195. source,
  196. insn: Insn {
  197. opc: 0x00,
  198. dst: 0x00,
  199. src: 0x00,
  200. off: 0x00_00,
  201. imm: 0x00_00_00_00,
  202. },
  203. }
  204. }
  205. /// creates STORE instruction, IMMEDIATE is the source
  206. pub fn store(&mut self, mem_size: MemSize) -> Store {
  207. self.store_internal(mem_size, BPF_IMM)
  208. }
  209. /// creates STORE instruction, MEMORY is the source
  210. pub fn store_x(&mut self, mem_size: MemSize) -> Store {
  211. self.store_internal(mem_size, BPF_MEM | BPF_STX)
  212. }
  213. #[inline]
  214. fn store_internal(&mut self, mem_size: MemSize, source: u8) -> Store {
  215. Store {
  216. bpf_code: self,
  217. mem_size,
  218. source,
  219. insn: Insn {
  220. opc: 0x00,
  221. dst: 0x00,
  222. src: 0x00,
  223. off: 0x00_00,
  224. imm: 0x00_00_00_00,
  225. },
  226. }
  227. }
  228. /// create unconditional JMP instruction
  229. pub fn jump_unconditional(&mut self) -> Jump {
  230. self.jump_conditional(Cond::Abs, Source::Imm)
  231. }
  232. /// create conditional JMP instruction
  233. pub fn jump_conditional(&mut self, cond: Cond, src_bit: Source) -> Jump {
  234. Jump {
  235. bpf_code: self,
  236. cond,
  237. src_bit,
  238. insn: Insn {
  239. opc: 0x00,
  240. dst: 0x00,
  241. src: 0x00,
  242. off: 0x00_00,
  243. imm: 0x00_00_00_00,
  244. },
  245. }
  246. }
  247. /// create CALL instruction
  248. pub fn call(&mut self) -> FunctionCall {
  249. FunctionCall {
  250. bpf_code: self,
  251. insn: Insn {
  252. opc: 0x00,
  253. dst: 0x00,
  254. src: 0x00,
  255. off: 0x00_00,
  256. imm: 0x00_00_00_00,
  257. },
  258. }
  259. }
  260. /// create EXIT instruction
  261. pub fn exit(&mut self) -> Exit {
  262. Exit {
  263. bpf_code: self,
  264. insn: Insn {
  265. opc: 0x00,
  266. dst: 0x00,
  267. src: 0x00,
  268. off: 0x00_00,
  269. imm: 0x00_00_00_00,
  270. },
  271. }
  272. }
  273. }
  274. /// Transform `BpfCode` into assemble representation
  275. impl<'a> IntoBytes for &'a BpfCode {
  276. type Bytes = &'a [u8];
  277. /// returns `BpfCode` instruction stack as `&[u8]`
  278. fn into_bytes(self) -> Self::Bytes {
  279. self.instructions.as_slice()
  280. }
  281. }
  282. /// struct to represent `MOV ALU` instructions
  283. pub struct Move<'i> {
  284. bpf_code: &'i mut BpfCode,
  285. src_bit: Source,
  286. op_bits: OpBits,
  287. arch_bits: Arch,
  288. insn: Insn,
  289. }
  290. impl<'i> Move<'i> {
  291. /// push MOV instruction into BpfCode instruction stack
  292. pub fn push(self) -> &'i mut BpfCode {
  293. let mut asm = self.into_bytes();
  294. self.bpf_code.instructions.append(&mut asm);
  295. self.bpf_code
  296. }
  297. }
  298. impl Instruction for Move<'_> {
  299. fn opt_code_byte(&self) -> u8 {
  300. let op_bits = self.op_bits as u8;
  301. let src_bit = self.src_bit as u8;
  302. let arch_bits = self.arch_bits as u8;
  303. op_bits | src_bit | arch_bits
  304. }
  305. fn get_insn_mut(&mut self) -> &mut Insn {
  306. &mut self.insn
  307. }
  308. fn get_insn(&self) -> &Insn {
  309. &self.insn
  310. }
  311. }
  312. #[derive(Copy, Clone, PartialEq, Eq)]
  313. /// The source of ALU and JMP instructions
  314. pub enum Source {
  315. /// immediate field will be used as a source
  316. Imm = BPF_IMM as isize,
  317. /// src register will be used as a source
  318. Reg = BPF_X as isize,
  319. }
  320. #[derive(Copy, Clone)]
  321. enum OpBits {
  322. Add = BPF_ADD as isize,
  323. Sub = BPF_SUB as isize,
  324. Mul = BPF_MUL as isize,
  325. Div = BPF_DIV as isize,
  326. BitOr = BPF_OR as isize,
  327. BitAnd = BPF_AND as isize,
  328. LShift = BPF_LSH as isize,
  329. RShift = BPF_RSH as isize,
  330. Negate = BPF_NEG as isize,
  331. Mod = BPF_MOD as isize,
  332. BitXor = BPF_XOR as isize,
  333. Mov = BPF_MOV as isize,
  334. SignRShift = BPF_ARSH as isize,
  335. }
  336. #[derive(Copy, Clone)]
  337. /// Architecture of instructions
  338. pub enum Arch {
  339. /// 64-bit instructions
  340. X64 = BPF_ALU64 as isize,
  341. /// 32-bit instructions
  342. X32 = BPF_ALU as isize,
  343. }
  344. /// struct representation of byte swap operation
  345. pub struct SwapBytes<'i> {
  346. bpf_code: &'i mut BpfCode,
  347. endian: Endian,
  348. insn: Insn,
  349. }
  350. impl<'i> SwapBytes<'i> {
  351. /// push bytes swap instruction into BpfCode instruction stack
  352. pub fn push(self) -> &'i mut BpfCode {
  353. let mut asm = self.into_bytes();
  354. self.bpf_code.instructions.append(&mut asm);
  355. self.bpf_code
  356. }
  357. }
  358. impl Instruction for SwapBytes<'_> {
  359. fn opt_code_byte(&self) -> u8 {
  360. self.endian as u8
  361. }
  362. fn get_insn_mut(&mut self) -> &mut Insn {
  363. &mut self.insn
  364. }
  365. fn get_insn(&self) -> &Insn {
  366. &self.insn
  367. }
  368. }
  369. #[derive(Copy, Clone)]
  370. /// Bytes endian
  371. pub enum Endian {
  372. /// Little endian
  373. Little = LE as isize,
  374. /// Big endian
  375. Big = BE as isize,
  376. }
  377. /// struct representation of LOAD instructions
  378. pub struct Load<'i> {
  379. bpf_code: &'i mut BpfCode,
  380. addressing: Addressing,
  381. mem_size: MemSize,
  382. source: u8,
  383. insn: Insn,
  384. }
  385. impl<'i> Load<'i> {
  386. /// push LOAD instruction into BpfCode instruction stack
  387. pub fn push(self) -> &'i mut BpfCode {
  388. let mut asm = self.into_bytes();
  389. self.bpf_code.instructions.append(&mut asm);
  390. self.bpf_code
  391. }
  392. }
  393. impl Instruction for Load<'_> {
  394. fn opt_code_byte(&self) -> u8 {
  395. let size = self.mem_size as u8;
  396. let addressing = self.addressing as u8;
  397. addressing | size | self.source
  398. }
  399. fn get_insn(&self) -> &Insn {
  400. &self.insn
  401. }
  402. fn get_insn_mut(&mut self) -> &mut Insn {
  403. &mut self.insn
  404. }
  405. }
  406. /// struct representation of STORE instructions
  407. pub struct Store<'i> {
  408. bpf_code: &'i mut BpfCode,
  409. mem_size: MemSize,
  410. source: u8,
  411. insn: Insn,
  412. }
  413. impl<'i> Store<'i> {
  414. /// push STORE instruction into BpfCode instruction stack
  415. pub fn push(self) -> &'i mut BpfCode {
  416. let mut asm = self.into_bytes();
  417. self.bpf_code.instructions.append(&mut asm);
  418. self.bpf_code
  419. }
  420. }
  421. impl Instruction for Store<'_> {
  422. fn opt_code_byte(&self) -> u8 {
  423. let size = self.mem_size as u8;
  424. BPF_MEM | BPF_ST | size | self.source
  425. }
  426. fn get_insn(&self) -> &Insn {
  427. &self.insn
  428. }
  429. fn get_insn_mut(&mut self) -> &mut Insn {
  430. &mut self.insn
  431. }
  432. }
  433. #[derive(Copy, Clone)]
  434. /// Memory size for LOAD and STORE instructions
  435. pub enum MemSize {
  436. /// 8-bit size
  437. Byte = BPF_B as isize,
  438. /// 16-bit size
  439. HalfWord = BPF_H as isize,
  440. /// 32-bit size
  441. Word = BPF_W as isize,
  442. /// 64-bit size
  443. DoubleWord = BPF_DW as isize,
  444. }
  445. #[derive(Copy, Clone)]
  446. enum Addressing {
  447. Imm = BPF_IMM as isize,
  448. Abs = BPF_ABS as isize,
  449. Ind = BPF_IND as isize,
  450. Mem = BPF_MEM as isize,
  451. }
  452. /// struct representation of JMP instructions
  453. pub struct Jump<'i> {
  454. bpf_code: &'i mut BpfCode,
  455. cond: Cond,
  456. src_bit: Source,
  457. insn: Insn,
  458. }
  459. impl<'i> Jump<'i> {
  460. /// push JMP instruction into BpfCode instruction stack
  461. pub fn push(self) -> &'i mut BpfCode {
  462. let mut asm = self.into_bytes();
  463. self.bpf_code.instructions.append(&mut asm);
  464. self.bpf_code
  465. }
  466. }
  467. impl Instruction for Jump<'_> {
  468. fn opt_code_byte(&self) -> u8 {
  469. let cmp: u8 = self.cond as u8;
  470. let src_bit = self.src_bit as u8;
  471. cmp | src_bit | BPF_JMP
  472. }
  473. fn get_insn(&self) -> &Insn {
  474. &self.insn
  475. }
  476. fn get_insn_mut(&mut self) -> &mut Insn {
  477. &mut self.insn
  478. }
  479. }
  480. #[derive(Copy, Clone, PartialEq, Eq)]
  481. /// Conditions for JMP instructions
  482. pub enum Cond {
  483. /// Absolute or unconditional
  484. Abs = BPF_JA as isize,
  485. /// Jump if `==`
  486. Equals = BPF_JEQ as isize,
  487. /// Jump if `>`
  488. Greater = BPF_JGT as isize,
  489. /// Jump if `>=`
  490. GreaterEquals = BPF_JGE as isize,
  491. /// Jump if `<`
  492. Lower = BPF_JLT as isize,
  493. /// Jump if `<=`
  494. LowerEquals = BPF_JLE as isize,
  495. /// Jump if `src` & `dst`
  496. BitAnd = BPF_JSET as isize,
  497. /// Jump if `!=`
  498. NotEquals = BPF_JNE as isize,
  499. /// Jump if `>` (signed)
  500. GreaterSigned = BPF_JSGT as isize,
  501. /// Jump if `>=` (signed)
  502. GreaterEqualsSigned = BPF_JSGE as isize,
  503. /// Jump if `<` (signed)
  504. LowerSigned = BPF_JSLT as isize,
  505. /// Jump if `<=` (signed)
  506. LowerEqualsSigned = BPF_JSLE as isize,
  507. }
  508. /// struct representation of CALL instruction
  509. pub struct FunctionCall<'i> {
  510. bpf_code: &'i mut BpfCode,
  511. insn: Insn,
  512. }
  513. impl<'i> FunctionCall<'i> {
  514. /// push CALL instruction into BpfCode instruction stack
  515. pub fn push(self) -> &'i mut BpfCode {
  516. let mut asm = self.into_bytes();
  517. self.bpf_code.instructions.append(&mut asm);
  518. self.bpf_code
  519. }
  520. }
  521. impl Instruction for FunctionCall<'_> {
  522. fn opt_code_byte(&self) -> u8 {
  523. BPF_CALL | BPF_JMP
  524. }
  525. fn get_insn(&self) -> &Insn {
  526. &self.insn
  527. }
  528. fn get_insn_mut(&mut self) -> &mut Insn {
  529. &mut self.insn
  530. }
  531. }
  532. /// struct representation of EXIT instruction
  533. pub struct Exit<'i> {
  534. bpf_code: &'i mut BpfCode,
  535. insn: Insn,
  536. }
  537. impl<'i> Exit<'i> {
  538. /// push EXIT instruction into BpfCode instruction stack
  539. pub fn push(self) -> &'i mut BpfCode {
  540. let mut asm = self.into_bytes();
  541. self.bpf_code.instructions.append(&mut asm);
  542. self.bpf_code
  543. }
  544. }
  545. impl Instruction for Exit<'_> {
  546. fn opt_code_byte(&self) -> u8 {
  547. BPF_EXIT | BPF_JMP
  548. }
  549. fn get_insn_mut(&mut self) -> &mut Insn {
  550. &mut self.insn
  551. }
  552. fn get_insn(&self) -> &Insn {
  553. &self.insn
  554. }
  555. }
  556. #[cfg(test)]
  557. mod tests {
  558. #[cfg(test)]
  559. mod special {
  560. use super::super::*;
  561. #[test]
  562. fn call_immediate() {
  563. let mut program = BpfCode::new();
  564. program.call().set_imm(0x11_22_33_44).push();
  565. assert_eq!(
  566. program.into_bytes(),
  567. &[0x85, 0x00, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
  568. );
  569. }
  570. #[test]
  571. fn exit_operation() {
  572. let mut program = BpfCode::new();
  573. program.exit().push();
  574. assert_eq!(
  575. program.into_bytes(),
  576. &[0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  577. );
  578. }
  579. }
  580. #[cfg(test)]
  581. mod jump_instructions {
  582. #[cfg(test)]
  583. mod register {
  584. use super::super::super::*;
  585. #[test]
  586. fn jump_on_dst_equals_src() {
  587. let mut program = BpfCode::new();
  588. program
  589. .jump_conditional(Cond::Equals, Source::Reg)
  590. .set_dst(0x01)
  591. .set_src(0x02)
  592. .push();
  593. assert_eq!(
  594. program.into_bytes(),
  595. &[0x1d, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  596. );
  597. }
  598. #[test]
  599. fn jump_on_dst_greater_than_src() {
  600. let mut program = BpfCode::new();
  601. program
  602. .jump_conditional(Cond::Greater, Source::Reg)
  603. .set_dst(0x03)
  604. .set_src(0x02)
  605. .push();
  606. assert_eq!(
  607. program.into_bytes(),
  608. &[0x2d, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  609. );
  610. }
  611. #[test]
  612. fn jump_on_dst_greater_or_equals_to_src() {
  613. let mut program = BpfCode::new();
  614. program
  615. .jump_conditional(Cond::GreaterEquals, Source::Reg)
  616. .set_dst(0x04)
  617. .set_src(0x01)
  618. .push();
  619. assert_eq!(
  620. program.into_bytes(),
  621. &[0x3d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  622. );
  623. }
  624. #[test]
  625. fn jump_on_dst_lower_than_src() {
  626. let mut program = BpfCode::new();
  627. program
  628. .jump_conditional(Cond::Lower, Source::Reg)
  629. .set_dst(0x03)
  630. .set_src(0x02)
  631. .push();
  632. assert_eq!(
  633. program.into_bytes(),
  634. &[0xad, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  635. );
  636. }
  637. #[test]
  638. fn jump_on_dst_lower_or_equals_to_src() {
  639. let mut program = BpfCode::new();
  640. program
  641. .jump_conditional(Cond::LowerEquals, Source::Reg)
  642. .set_dst(0x04)
  643. .set_src(0x01)
  644. .push();
  645. assert_eq!(
  646. program.into_bytes(),
  647. &[0xbd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  648. );
  649. }
  650. #[test]
  651. fn jump_on_dst_bit_and_with_src_not_equal_zero() {
  652. let mut program = BpfCode::new();
  653. program
  654. .jump_conditional(Cond::BitAnd, Source::Reg)
  655. .set_dst(0x05)
  656. .set_src(0x02)
  657. .push();
  658. assert_eq!(
  659. program.into_bytes(),
  660. &[0x4d, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  661. );
  662. }
  663. #[test]
  664. fn jump_on_dst_not_equals_src() {
  665. let mut program = BpfCode::new();
  666. program
  667. .jump_conditional(Cond::NotEquals, Source::Reg)
  668. .set_dst(0x03)
  669. .set_src(0x05)
  670. .push();
  671. assert_eq!(
  672. program.into_bytes(),
  673. &[0x5d, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  674. );
  675. }
  676. #[test]
  677. fn jump_on_dst_greater_than_src_signed() {
  678. let mut program = BpfCode::new();
  679. program
  680. .jump_conditional(Cond::GreaterSigned, Source::Reg)
  681. .set_dst(0x04)
  682. .set_src(0x01)
  683. .push();
  684. assert_eq!(
  685. program.into_bytes(),
  686. &[0x6d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  687. );
  688. }
  689. #[test]
  690. fn jump_on_dst_greater_or_equals_src_signed() {
  691. let mut program = BpfCode::new();
  692. program
  693. .jump_conditional(Cond::GreaterEqualsSigned, Source::Reg)
  694. .set_dst(0x01)
  695. .set_src(0x03)
  696. .push();
  697. assert_eq!(
  698. program.into_bytes(),
  699. &[0x7d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  700. );
  701. }
  702. #[test]
  703. fn jump_on_dst_lower_than_src_signed() {
  704. let mut program = BpfCode::new();
  705. program
  706. .jump_conditional(Cond::LowerSigned, Source::Reg)
  707. .set_dst(0x04)
  708. .set_src(0x01)
  709. .push();
  710. assert_eq!(
  711. program.into_bytes(),
  712. &[0xcd, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  713. );
  714. }
  715. #[test]
  716. fn jump_on_dst_lower_or_equals_src_signed() {
  717. let mut program = BpfCode::new();
  718. program
  719. .jump_conditional(Cond::LowerEqualsSigned, Source::Reg)
  720. .set_dst(0x01)
  721. .set_src(0x03)
  722. .push();
  723. assert_eq!(
  724. program.into_bytes(),
  725. &[0xdd, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  726. );
  727. }
  728. }
  729. #[cfg(test)]
  730. mod immediate {
  731. use super::super::super::*;
  732. #[test]
  733. fn jump_to_label() {
  734. let mut program = BpfCode::new();
  735. program.jump_unconditional().set_off(0x00_11).push();
  736. assert_eq!(
  737. program.into_bytes(),
  738. &[0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]
  739. );
  740. }
  741. #[test]
  742. fn jump_on_dst_equals_const() {
  743. let mut program = BpfCode::new();
  744. program
  745. .jump_conditional(Cond::Equals, Source::Imm)
  746. .set_dst(0x01)
  747. .set_imm(0x00_11_22_33)
  748. .push();
  749. assert_eq!(
  750. program.into_bytes(),
  751. &[0x15, 0x01, 0x00, 0x00, 0x33, 0x22, 0x11, 0x00]
  752. );
  753. }
  754. #[test]
  755. fn jump_on_dst_greater_than_const() {
  756. let mut program = BpfCode::new();
  757. program
  758. .jump_conditional(Cond::Greater, Source::Imm)
  759. .set_dst(0x02)
  760. .set_imm(0x00_11_00_11)
  761. .push();
  762. assert_eq!(
  763. program.into_bytes(),
  764. &[0x25, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]
  765. );
  766. }
  767. #[test]
  768. fn jump_on_dst_greater_or_equals_to_const() {
  769. let mut program = BpfCode::new();
  770. program
  771. .jump_conditional(Cond::GreaterEquals, Source::Imm)
  772. .set_dst(0x04)
  773. .set_imm(0x00_22_11_00)
  774. .push();
  775. assert_eq!(
  776. program.into_bytes(),
  777. &[0x35, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]
  778. );
  779. }
  780. #[test]
  781. fn jump_on_dst_lower_than_const() {
  782. let mut program = BpfCode::new();
  783. program
  784. .jump_conditional(Cond::Lower, Source::Imm)
  785. .set_dst(0x02)
  786. .set_imm(0x00_11_00_11)
  787. .push();
  788. assert_eq!(
  789. program.into_bytes(),
  790. &[0xa5, 0x02, 0x00, 0x00, 0x11, 0x00, 0x11, 0x00]
  791. );
  792. }
  793. #[test]
  794. fn jump_on_dst_lower_or_equals_to_const() {
  795. let mut program = BpfCode::new();
  796. program
  797. .jump_conditional(Cond::LowerEquals, Source::Imm)
  798. .set_dst(0x04)
  799. .set_imm(0x00_22_11_00)
  800. .push();
  801. assert_eq!(
  802. program.into_bytes(),
  803. &[0xb5, 0x04, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00]
  804. );
  805. }
  806. #[test]
  807. fn jump_on_dst_bit_and_with_const_not_equal_zero() {
  808. let mut program = BpfCode::new();
  809. program
  810. .jump_conditional(Cond::BitAnd, Source::Imm)
  811. .set_dst(0x05)
  812. .push();
  813. assert_eq!(
  814. program.into_bytes(),
  815. &[0x45, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  816. );
  817. }
  818. #[test]
  819. fn jump_on_dst_not_equals_const() {
  820. let mut program = BpfCode::new();
  821. program
  822. .jump_conditional(Cond::NotEquals, Source::Imm)
  823. .set_dst(0x03)
  824. .push();
  825. assert_eq!(
  826. program.into_bytes(),
  827. &[0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  828. );
  829. }
  830. #[test]
  831. fn jump_on_dst_greater_than_const_signed() {
  832. let mut program = BpfCode::new();
  833. program
  834. .jump_conditional(Cond::GreaterSigned, Source::Imm)
  835. .set_dst(0x04)
  836. .push();
  837. assert_eq!(
  838. program.into_bytes(),
  839. &[0x65, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  840. );
  841. }
  842. #[test]
  843. fn jump_on_dst_greater_or_equals_src_signed() {
  844. let mut program = BpfCode::new();
  845. program
  846. .jump_conditional(Cond::GreaterEqualsSigned, Source::Imm)
  847. .set_dst(0x01)
  848. .push();
  849. assert_eq!(
  850. program.into_bytes(),
  851. &[0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  852. );
  853. }
  854. #[test]
  855. fn jump_on_dst_lower_than_const_signed() {
  856. let mut program = BpfCode::new();
  857. program
  858. .jump_conditional(Cond::LowerSigned, Source::Imm)
  859. .set_dst(0x04)
  860. .push();
  861. assert_eq!(
  862. program.into_bytes(),
  863. &[0xc5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  864. );
  865. }
  866. #[test]
  867. fn jump_on_dst_lower_or_equals_src_signed() {
  868. let mut program = BpfCode::new();
  869. program
  870. .jump_conditional(Cond::LowerEqualsSigned, Source::Imm)
  871. .set_dst(0x01)
  872. .push();
  873. assert_eq!(
  874. program.into_bytes(),
  875. &[0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  876. );
  877. }
  878. }
  879. }
  880. #[cfg(test)]
  881. mod store_instructions {
  882. use super::super::*;
  883. #[test]
  884. fn store_word_from_dst_into_immediate_address() {
  885. let mut program = BpfCode::new();
  886. program
  887. .store(MemSize::Word)
  888. .set_dst(0x01)
  889. .set_off(0x00_11)
  890. .set_imm(0x11_22_33_44)
  891. .push();
  892. assert_eq!(
  893. program.into_bytes(),
  894. &[0x62, 0x01, 0x11, 0x00, 0x44, 0x33, 0x22, 0x11]
  895. );
  896. }
  897. #[test]
  898. fn store_half_word_from_dst_into_immediate_address() {
  899. let mut program = BpfCode::new();
  900. program
  901. .store(MemSize::HalfWord)
  902. .set_dst(0x02)
  903. .set_off(0x11_22)
  904. .push();
  905. assert_eq!(
  906. program.into_bytes(),
  907. &[0x6a, 0x02, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]
  908. );
  909. }
  910. #[test]
  911. fn store_byte_from_dst_into_immediate_address() {
  912. let mut program = BpfCode::new();
  913. program.store(MemSize::Byte).push();
  914. assert_eq!(
  915. program.into_bytes(),
  916. &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  917. );
  918. }
  919. #[test]
  920. fn store_double_word_from_dst_into_immediate_address() {
  921. let mut program = BpfCode::new();
  922. program.store(MemSize::DoubleWord).push();
  923. assert_eq!(
  924. program.into_bytes(),
  925. &[0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  926. );
  927. }
  928. #[test]
  929. fn store_word_from_dst_into_src_address() {
  930. let mut program = BpfCode::new();
  931. program
  932. .store_x(MemSize::Word)
  933. .set_dst(0x01)
  934. .set_src(0x02)
  935. .push();
  936. assert_eq!(
  937. program.into_bytes(),
  938. &[0x63, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  939. );
  940. }
  941. #[test]
  942. fn store_half_word_from_dst_into_src_address() {
  943. let mut program = BpfCode::new();
  944. program.store_x(MemSize::HalfWord).push();
  945. assert_eq!(
  946. program.into_bytes(),
  947. &[0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  948. );
  949. }
  950. #[test]
  951. fn store_byte_from_dst_into_src_address() {
  952. let mut program = BpfCode::new();
  953. program.store_x(MemSize::Byte).push();
  954. assert_eq!(
  955. program.into_bytes(),
  956. &[0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  957. );
  958. }
  959. #[test]
  960. fn store_double_word_from_dst_into_src_address() {
  961. let mut program = BpfCode::new();
  962. program.store_x(MemSize::DoubleWord).push();
  963. assert_eq!(
  964. program.into_bytes(),
  965. &[0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  966. );
  967. }
  968. }
  969. #[cfg(test)]
  970. mod load_instructions {
  971. #[cfg(test)]
  972. mod register {
  973. use super::super::super::*;
  974. #[test]
  975. fn load_word_from_set_src_with_offset() {
  976. let mut program = BpfCode::new();
  977. program
  978. .load_x(MemSize::Word)
  979. .set_dst(0x01)
  980. .set_src(0x02)
  981. .set_off(0x00_02)
  982. .push();
  983. assert_eq!(
  984. program.into_bytes(),
  985. &[0x61, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00]
  986. );
  987. }
  988. #[test]
  989. fn load_half_word_from_set_src_with_offset() {
  990. let mut program = BpfCode::new();
  991. program
  992. .load_x(MemSize::HalfWord)
  993. .set_dst(0x02)
  994. .set_src(0x01)
  995. .set_off(0x11_22)
  996. .push();
  997. assert_eq!(
  998. program.into_bytes(),
  999. &[0x69, 0x12, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00]
  1000. );
  1001. }
  1002. #[test]
  1003. fn load_byte_from_set_src_with_offset() {
  1004. let mut program = BpfCode::new();
  1005. program
  1006. .load_x(MemSize::Byte)
  1007. .set_dst(0x01)
  1008. .set_src(0x04)
  1009. .set_off(0x00_11)
  1010. .push();
  1011. assert_eq!(
  1012. program.into_bytes(),
  1013. &[0x71, 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00]
  1014. );
  1015. }
  1016. #[test]
  1017. fn load_double_word_from_set_src_with_offset() {
  1018. let mut program = BpfCode::new();
  1019. program
  1020. .load_x(MemSize::DoubleWord)
  1021. .set_dst(0x04)
  1022. .set_src(0x05)
  1023. .set_off(0x44_55)
  1024. .push();
  1025. assert_eq!(
  1026. program.into_bytes(),
  1027. &[0x79, 0x54, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00]
  1028. );
  1029. }
  1030. }
  1031. #[cfg(test)]
  1032. mod immediate {
  1033. use super::super::super::*;
  1034. #[test]
  1035. fn load_double_word() {
  1036. let mut program = BpfCode::new();
  1037. program
  1038. .load(MemSize::DoubleWord)
  1039. .set_dst(0x01)
  1040. .set_imm(0x00_01_02_03)
  1041. .push();
  1042. assert_eq!(
  1043. program.into_bytes(),
  1044. &[0x18, 0x01, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
  1045. );
  1046. }
  1047. #[test]
  1048. fn load_abs_word() {
  1049. let mut program = BpfCode::new();
  1050. program.load_abs(MemSize::Word).push();
  1051. assert_eq!(
  1052. program.into_bytes(),
  1053. &[0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1054. );
  1055. }
  1056. #[test]
  1057. fn load_abs_half_word() {
  1058. let mut program = BpfCode::new();
  1059. program.load_abs(MemSize::HalfWord).set_dst(0x05).push();
  1060. assert_eq!(
  1061. program.into_bytes(),
  1062. &[0x28, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1063. );
  1064. }
  1065. #[test]
  1066. fn load_abs_byte() {
  1067. let mut program = BpfCode::new();
  1068. program.load_abs(MemSize::Byte).set_dst(0x01).push();
  1069. assert_eq!(
  1070. program.into_bytes(),
  1071. &[0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1072. );
  1073. }
  1074. #[test]
  1075. fn load_abs_double_word() {
  1076. let mut program = BpfCode::new();
  1077. program
  1078. .load_abs(MemSize::DoubleWord)
  1079. .set_dst(0x01)
  1080. .set_imm(0x01_02_03_04)
  1081. .push();
  1082. assert_eq!(
  1083. program.into_bytes(),
  1084. &[0x38, 0x01, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
  1085. );
  1086. }
  1087. #[test]
  1088. fn load_indirect_word() {
  1089. let mut program = BpfCode::new();
  1090. program.load_ind(MemSize::Word).push();
  1091. assert_eq!(
  1092. program.into_bytes(),
  1093. &[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1094. );
  1095. }
  1096. #[test]
  1097. fn load_indirect_half_word() {
  1098. let mut program = BpfCode::new();
  1099. program.load_ind(MemSize::HalfWord).push();
  1100. assert_eq!(
  1101. program.into_bytes(),
  1102. &[0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1103. );
  1104. }
  1105. #[test]
  1106. fn load_indirect_byte() {
  1107. let mut program = BpfCode::new();
  1108. program.load_ind(MemSize::Byte).push();
  1109. assert_eq!(
  1110. program.into_bytes(),
  1111. &[0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1112. );
  1113. }
  1114. #[test]
  1115. fn load_indirect_double_word() {
  1116. let mut program = BpfCode::new();
  1117. program.load_ind(MemSize::DoubleWord).push();
  1118. assert_eq!(
  1119. program.into_bytes(),
  1120. &[0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1121. );
  1122. }
  1123. }
  1124. }
  1125. #[cfg(test)]
  1126. mod byte_swap_instructions {
  1127. use super::super::*;
  1128. #[test]
  1129. fn convert_host_to_little_endian_16bits() {
  1130. let mut program = BpfCode::new();
  1131. program
  1132. .swap_bytes(Endian::Little)
  1133. .set_dst(0x01)
  1134. .set_imm(0x00_00_00_10)
  1135. .push();
  1136. assert_eq!(
  1137. program.into_bytes(),
  1138. &[0xd4, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]
  1139. );
  1140. }
  1141. #[test]
  1142. fn convert_host_to_little_endian_32bits() {
  1143. let mut program = BpfCode::new();
  1144. program
  1145. .swap_bytes(Endian::Little)
  1146. .set_dst(0x02)
  1147. .set_imm(0x00_00_00_20)
  1148. .push();
  1149. assert_eq!(
  1150. program.into_bytes(),
  1151. &[0xd4, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]
  1152. );
  1153. }
  1154. #[test]
  1155. fn convert_host_to_little_endian_64bit() {
  1156. let mut program = BpfCode::new();
  1157. program
  1158. .swap_bytes(Endian::Little)
  1159. .set_dst(0x03)
  1160. .set_imm(0x00_00_00_40)
  1161. .push();
  1162. assert_eq!(
  1163. program.into_bytes(),
  1164. &[0xd4, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]
  1165. );
  1166. }
  1167. #[test]
  1168. fn convert_host_to_big_endian_16bits() {
  1169. let mut program = BpfCode::new();
  1170. program
  1171. .swap_bytes(Endian::Big)
  1172. .set_dst(0x01)
  1173. .set_imm(0x00_00_00_10)
  1174. .push();
  1175. assert_eq!(
  1176. program.into_bytes(),
  1177. &[0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00]
  1178. );
  1179. }
  1180. #[test]
  1181. fn convert_host_to_big_endian_32bits() {
  1182. let mut program = BpfCode::new();
  1183. program
  1184. .swap_bytes(Endian::Big)
  1185. .set_dst(0x02)
  1186. .set_imm(0x00_00_00_20)
  1187. .push();
  1188. assert_eq!(
  1189. program.into_bytes(),
  1190. &[0xdc, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]
  1191. );
  1192. }
  1193. #[test]
  1194. fn convert_host_to_big_endian_64bit() {
  1195. let mut program = BpfCode::new();
  1196. program
  1197. .swap_bytes(Endian::Big)
  1198. .set_dst(0x03)
  1199. .set_imm(0x00_00_00_40)
  1200. .push();
  1201. assert_eq!(
  1202. program.into_bytes(),
  1203. &[0xdc, 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00]
  1204. );
  1205. }
  1206. }
  1207. #[cfg(test)]
  1208. mod moves_instructions {
  1209. #[cfg(test)]
  1210. mod arch_x64 {
  1211. #[cfg(test)]
  1212. mod immediate {
  1213. use super::super::super::super::*;
  1214. #[test]
  1215. fn move_and_add_const_to_register() {
  1216. let mut program = BpfCode::new();
  1217. program
  1218. .add(Source::Imm, Arch::X64)
  1219. .set_dst(0x02)
  1220. .set_imm(0x01_02_03_04)
  1221. .push();
  1222. assert_eq!(
  1223. program.into_bytes(),
  1224. &[0x07, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
  1225. );
  1226. }
  1227. #[test]
  1228. fn move_sub_const_to_register() {
  1229. let mut program = BpfCode::new();
  1230. program
  1231. .sub(Source::Imm, Arch::X64)
  1232. .set_dst(0x04)
  1233. .set_imm(0x00_01_02_03)
  1234. .push();
  1235. assert_eq!(
  1236. program.into_bytes(),
  1237. &[0x17, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
  1238. );
  1239. }
  1240. #[test]
  1241. fn move_mul_const_to_register() {
  1242. let mut program = BpfCode::new();
  1243. program
  1244. .mul(Source::Imm, Arch::X64)
  1245. .set_dst(0x05)
  1246. .set_imm(0x04_03_02_01)
  1247. .push();
  1248. assert_eq!(
  1249. program.into_bytes(),
  1250. &[0x27, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]
  1251. );
  1252. }
  1253. #[test]
  1254. fn move_div_constant_to_register() {
  1255. let mut program = BpfCode::new();
  1256. program
  1257. .div(Source::Imm, Arch::X64)
  1258. .set_dst(0x02)
  1259. .set_imm(0x00_ff_00_ff)
  1260. .push();
  1261. assert_eq!(
  1262. program.into_bytes(),
  1263. &[0x37, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]
  1264. );
  1265. }
  1266. #[test]
  1267. fn move_bit_or_const_to_register() {
  1268. let mut program = BpfCode::new();
  1269. program
  1270. .bit_or(Source::Imm, Arch::X64)
  1271. .set_dst(0x02)
  1272. .set_imm(0x00_11_00_22)
  1273. .push();
  1274. assert_eq!(
  1275. program.into_bytes(),
  1276. &[0x47, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]
  1277. );
  1278. }
  1279. #[test]
  1280. fn move_bit_and_const_to_register() {
  1281. let mut program = BpfCode::new();
  1282. program
  1283. .bit_and(Source::Imm, Arch::X64)
  1284. .set_dst(0x02)
  1285. .set_imm(0x11_22_33_44)
  1286. .push();
  1287. assert_eq!(
  1288. program.into_bytes(),
  1289. &[0x57, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
  1290. );
  1291. }
  1292. #[test]
  1293. fn move_left_shift_const_to_register() {
  1294. let mut program = BpfCode::new();
  1295. program
  1296. .left_shift(Source::Imm, Arch::X64)
  1297. .set_dst(0x01)
  1298. .push();
  1299. assert_eq!(
  1300. program.into_bytes(),
  1301. &[0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1302. );
  1303. }
  1304. #[test]
  1305. fn move_logical_right_shift_const_to_register() {
  1306. let mut program = BpfCode::new();
  1307. program
  1308. .right_shift(Source::Imm, Arch::X64)
  1309. .set_dst(0x01)
  1310. .push();
  1311. assert_eq!(
  1312. program.into_bytes(),
  1313. &[0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1314. );
  1315. }
  1316. #[test]
  1317. fn move_negate_register() {
  1318. let mut program = BpfCode::new();
  1319. program.negate(Arch::X64).set_dst(0x02).push();
  1320. assert_eq!(
  1321. program.into_bytes(),
  1322. &[0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1323. );
  1324. }
  1325. #[test]
  1326. fn move_mod_const_to_register() {
  1327. let mut program = BpfCode::new();
  1328. program.modulo(Source::Imm, Arch::X64).set_dst(0x02).push();
  1329. assert_eq!(
  1330. program.into_bytes(),
  1331. &[0x97, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1332. );
  1333. }
  1334. #[test]
  1335. fn move_bit_xor_const_to_register() {
  1336. let mut program = BpfCode::new();
  1337. program.bit_xor(Source::Imm, Arch::X64).set_dst(0x03).push();
  1338. assert_eq!(
  1339. program.into_bytes(),
  1340. &[0xa7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1341. );
  1342. }
  1343. #[test]
  1344. fn move_const_to_register() {
  1345. let mut program = BpfCode::new();
  1346. program
  1347. .mov(Source::Imm, Arch::X64)
  1348. .set_dst(0x01)
  1349. .set_imm(0x00_00_00_FF)
  1350. .push();
  1351. assert_eq!(
  1352. program.into_bytes(),
  1353. &[0xb7, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]
  1354. );
  1355. }
  1356. #[test]
  1357. fn move_signed_right_shift_const_to_register() {
  1358. let mut program = BpfCode::new();
  1359. program
  1360. .signed_right_shift(Source::Imm, Arch::X64)
  1361. .set_dst(0x05)
  1362. .push();
  1363. assert_eq!(
  1364. program.into_bytes(),
  1365. &[0xc7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1366. );
  1367. }
  1368. }
  1369. #[cfg(test)]
  1370. mod register {
  1371. use super::super::super::super::*;
  1372. #[test]
  1373. fn move_and_add_from_register() {
  1374. let mut program = BpfCode::new();
  1375. program
  1376. .add(Source::Reg, Arch::X64)
  1377. .set_dst(0x03)
  1378. .set_src(0x02)
  1379. .push();
  1380. assert_eq!(
  1381. program.into_bytes(),
  1382. &[0x0f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1383. );
  1384. }
  1385. #[test]
  1386. fn move_sub_from_register_to_register() {
  1387. let mut program = BpfCode::new();
  1388. program
  1389. .sub(Source::Reg, Arch::X64)
  1390. .set_dst(0x03)
  1391. .set_src(0x04)
  1392. .push();
  1393. assert_eq!(
  1394. program.into_bytes(),
  1395. &[0x1f, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1396. );
  1397. }
  1398. #[test]
  1399. fn move_mul_from_register_to_register() {
  1400. let mut program = BpfCode::new();
  1401. program
  1402. .mul(Source::Reg, Arch::X64)
  1403. .set_dst(0x04)
  1404. .set_src(0x03)
  1405. .push();
  1406. assert_eq!(
  1407. program.into_bytes(),
  1408. &[0x2f, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1409. );
  1410. }
  1411. #[test]
  1412. fn move_div_from_register_to_register() {
  1413. let mut program = BpfCode::new();
  1414. program
  1415. .div(Source::Reg, Arch::X64)
  1416. .set_dst(0x01)
  1417. .set_src(0x00)
  1418. .push();
  1419. assert_eq!(
  1420. program.into_bytes(),
  1421. &[0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1422. );
  1423. }
  1424. #[test]
  1425. fn move_bit_or_from_register_to_register() {
  1426. let mut program = BpfCode::new();
  1427. program
  1428. .bit_or(Source::Reg, Arch::X64)
  1429. .set_dst(0x03)
  1430. .set_src(0x01)
  1431. .push();
  1432. assert_eq!(
  1433. program.into_bytes(),
  1434. &[0x4f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1435. );
  1436. }
  1437. #[test]
  1438. fn move_bit_and_from_register_to_register() {
  1439. let mut program = BpfCode::new();
  1440. program
  1441. .bit_and(Source::Reg, Arch::X64)
  1442. .set_dst(0x03)
  1443. .set_src(0x02)
  1444. .push();
  1445. assert_eq!(
  1446. program.into_bytes(),
  1447. &[0x5f, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1448. );
  1449. }
  1450. #[test]
  1451. fn move_left_shift_from_register_to_register() {
  1452. let mut program = BpfCode::new();
  1453. program
  1454. .left_shift(Source::Reg, Arch::X64)
  1455. .set_dst(0x02)
  1456. .set_src(0x03)
  1457. .push();
  1458. assert_eq!(
  1459. program.into_bytes(),
  1460. &[0x6f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1461. );
  1462. }
  1463. #[test]
  1464. fn move_logical_right_shift_from_register_to_register() {
  1465. let mut program = BpfCode::new();
  1466. program
  1467. .right_shift(Source::Reg, Arch::X64)
  1468. .set_dst(0x02)
  1469. .set_src(0x04)
  1470. .push();
  1471. assert_eq!(
  1472. program.into_bytes(),
  1473. &[0x7f, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1474. );
  1475. }
  1476. #[test]
  1477. fn move_mod_from_register_to_register() {
  1478. let mut program = BpfCode::new();
  1479. program
  1480. .modulo(Source::Reg, Arch::X64)
  1481. .set_dst(0x01)
  1482. .set_src(0x02)
  1483. .push();
  1484. assert_eq!(
  1485. program.into_bytes(),
  1486. &[0x9f, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1487. );
  1488. }
  1489. #[test]
  1490. fn move_bit_xor_from_register_to_register() {
  1491. let mut program = BpfCode::new();
  1492. program
  1493. .bit_xor(Source::Reg, Arch::X64)
  1494. .set_dst(0x02)
  1495. .set_src(0x04)
  1496. .push();
  1497. assert_eq!(
  1498. program.into_bytes(),
  1499. &[0xaf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1500. );
  1501. }
  1502. #[test]
  1503. fn move_from_register_to_another_register() {
  1504. let mut program = BpfCode::new();
  1505. program.mov(Source::Reg, Arch::X64).set_src(0x01).push();
  1506. assert_eq!(
  1507. program.into_bytes(),
  1508. &[0xbf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1509. );
  1510. }
  1511. #[test]
  1512. fn move_signed_right_shift_from_register_to_register() {
  1513. let mut program = BpfCode::new();
  1514. program
  1515. .signed_right_shift(Source::Reg, Arch::X64)
  1516. .set_dst(0x02)
  1517. .set_src(0x03)
  1518. .push();
  1519. assert_eq!(
  1520. program.into_bytes(),
  1521. &[0xcf, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1522. );
  1523. }
  1524. }
  1525. }
  1526. #[cfg(test)]
  1527. mod arch_x32 {
  1528. #[cfg(test)]
  1529. mod immediate {
  1530. use super::super::super::super::*;
  1531. #[test]
  1532. fn move_and_add_const_to_register() {
  1533. let mut program = BpfCode::new();
  1534. program
  1535. .add(Source::Imm, Arch::X32)
  1536. .set_dst(0x02)
  1537. .set_imm(0x01_02_03_04)
  1538. .push();
  1539. assert_eq!(
  1540. program.into_bytes(),
  1541. &[0x04, 0x02, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01]
  1542. );
  1543. }
  1544. #[test]
  1545. fn move_sub_const_to_register() {
  1546. let mut program = BpfCode::new();
  1547. program
  1548. .sub(Source::Imm, Arch::X32)
  1549. .set_dst(0x04)
  1550. .set_imm(0x00_01_02_03)
  1551. .push();
  1552. assert_eq!(
  1553. program.into_bytes(),
  1554. &[0x14, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00]
  1555. );
  1556. }
  1557. #[test]
  1558. fn move_mul_const_to_register() {
  1559. let mut program = BpfCode::new();
  1560. program
  1561. .mul(Source::Imm, Arch::X32)
  1562. .set_dst(0x05)
  1563. .set_imm(0x04_03_02_01)
  1564. .push();
  1565. assert_eq!(
  1566. program.into_bytes(),
  1567. &[0x24, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]
  1568. );
  1569. }
  1570. #[test]
  1571. fn move_div_constant_to_register() {
  1572. let mut program = BpfCode::new();
  1573. program
  1574. .div(Source::Imm, Arch::X32)
  1575. .set_dst(0x02)
  1576. .set_imm(0x00_ff_00_ff)
  1577. .push();
  1578. assert_eq!(
  1579. program.into_bytes(),
  1580. &[0x34, 0x02, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00]
  1581. );
  1582. }
  1583. #[test]
  1584. fn move_bit_or_const_to_register() {
  1585. let mut program = BpfCode::new();
  1586. program
  1587. .bit_or(Source::Imm, Arch::X32)
  1588. .set_dst(0x02)
  1589. .set_imm(0x00_11_00_22)
  1590. .push();
  1591. assert_eq!(
  1592. program.into_bytes(),
  1593. &[0x44, 0x02, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00]
  1594. );
  1595. }
  1596. #[test]
  1597. fn move_bit_and_const_to_register() {
  1598. let mut program = BpfCode::new();
  1599. program
  1600. .bit_and(Source::Imm, Arch::X32)
  1601. .set_dst(0x02)
  1602. .set_imm(0x11_22_33_44)
  1603. .push();
  1604. assert_eq!(
  1605. program.into_bytes(),
  1606. &[0x54, 0x02, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11]
  1607. );
  1608. }
  1609. #[test]
  1610. fn move_left_shift_const_to_register() {
  1611. let mut program = BpfCode::new();
  1612. program
  1613. .left_shift(Source::Imm, Arch::X32)
  1614. .set_dst(0x01)
  1615. .push();
  1616. assert_eq!(
  1617. program.into_bytes(),
  1618. &[0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1619. );
  1620. }
  1621. #[test]
  1622. fn move_logical_right_shift_const_to_register() {
  1623. let mut program = BpfCode::new();
  1624. program
  1625. .right_shift(Source::Imm, Arch::X32)
  1626. .set_dst(0x01)
  1627. .push();
  1628. assert_eq!(
  1629. program.into_bytes(),
  1630. &[0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1631. );
  1632. }
  1633. #[test]
  1634. fn move_negate_register() {
  1635. let mut program = BpfCode::new();
  1636. program.negate(Arch::X32).set_dst(0x02).push();
  1637. assert_eq!(
  1638. program.into_bytes(),
  1639. &[0x84, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1640. );
  1641. }
  1642. #[test]
  1643. fn move_mod_const_to_register() {
  1644. let mut program = BpfCode::new();
  1645. program.modulo(Source::Imm, Arch::X32).set_dst(0x02).push();
  1646. assert_eq!(
  1647. program.into_bytes(),
  1648. &[0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1649. );
  1650. }
  1651. #[test]
  1652. fn move_bit_xor_const_to_register() {
  1653. let mut program = BpfCode::new();
  1654. program.bit_xor(Source::Imm, Arch::X32).set_dst(0x03).push();
  1655. assert_eq!(
  1656. program.into_bytes(),
  1657. &[0xa4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1658. );
  1659. }
  1660. #[test]
  1661. fn move_const_to_register() {
  1662. let mut program = BpfCode::new();
  1663. program
  1664. .mov(Source::Imm, Arch::X32)
  1665. .set_dst(0x01)
  1666. .set_imm(0x00_00_00_FF)
  1667. .push();
  1668. assert_eq!(
  1669. program.into_bytes(),
  1670. &[0xb4, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00]
  1671. );
  1672. }
  1673. #[test]
  1674. fn move_signed_right_shift_const_to_register() {
  1675. let mut program = BpfCode::new();
  1676. program
  1677. .signed_right_shift(Source::Imm, Arch::X32)
  1678. .set_dst(0x05)
  1679. .push();
  1680. assert_eq!(
  1681. program.into_bytes(),
  1682. &[0xc4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1683. );
  1684. }
  1685. }
  1686. #[cfg(test)]
  1687. mod register {
  1688. use super::super::super::super::*;
  1689. #[test]
  1690. fn move_and_add_from_register() {
  1691. let mut program = BpfCode::new();
  1692. program
  1693. .add(Source::Reg, Arch::X32)
  1694. .set_dst(0x03)
  1695. .set_src(0x02)
  1696. .push();
  1697. assert_eq!(
  1698. program.into_bytes(),
  1699. &[0x0c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1700. );
  1701. }
  1702. #[test]
  1703. fn move_sub_from_register_to_register() {
  1704. let mut program = BpfCode::new();
  1705. program
  1706. .sub(Source::Reg, Arch::X32)
  1707. .set_dst(0x03)
  1708. .set_src(0x04)
  1709. .push();
  1710. assert_eq!(
  1711. program.into_bytes(),
  1712. &[0x1c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1713. );
  1714. }
  1715. #[test]
  1716. fn move_mul_from_register_to_register() {
  1717. let mut program = BpfCode::new();
  1718. program
  1719. .mul(Source::Reg, Arch::X32)
  1720. .set_dst(0x04)
  1721. .set_src(0x03)
  1722. .push();
  1723. assert_eq!(
  1724. program.into_bytes(),
  1725. &[0x2c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1726. );
  1727. }
  1728. #[test]
  1729. fn move_div_from_register_to_register() {
  1730. let mut program = BpfCode::new();
  1731. program
  1732. .div(Source::Reg, Arch::X32)
  1733. .set_dst(0x01)
  1734. .set_src(0x00)
  1735. .push();
  1736. assert_eq!(
  1737. program.into_bytes(),
  1738. &[0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1739. );
  1740. }
  1741. #[test]
  1742. fn move_bit_or_from_register_to_register() {
  1743. let mut program = BpfCode::new();
  1744. program
  1745. .bit_or(Source::Reg, Arch::X32)
  1746. .set_dst(0x03)
  1747. .set_src(0x01)
  1748. .push();
  1749. assert_eq!(
  1750. program.into_bytes(),
  1751. &[0x4c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1752. );
  1753. }
  1754. #[test]
  1755. fn move_bit_and_from_register_to_register() {
  1756. let mut program = BpfCode::new();
  1757. program
  1758. .bit_and(Source::Reg, Arch::X32)
  1759. .set_dst(0x03)
  1760. .set_src(0x02)
  1761. .push();
  1762. assert_eq!(
  1763. program.into_bytes(),
  1764. &[0x5c, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1765. );
  1766. }
  1767. #[test]
  1768. fn move_left_shift_from_register_to_register() {
  1769. let mut program = BpfCode::new();
  1770. program
  1771. .left_shift(Source::Reg, Arch::X32)
  1772. .set_dst(0x02)
  1773. .set_src(0x03)
  1774. .push();
  1775. assert_eq!(
  1776. program.into_bytes(),
  1777. &[0x6c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1778. );
  1779. }
  1780. #[test]
  1781. fn move_logical_right_shift_from_register_to_register() {
  1782. let mut program = BpfCode::new();
  1783. program
  1784. .right_shift(Source::Reg, Arch::X32)
  1785. .set_dst(0x02)
  1786. .set_src(0x04)
  1787. .push();
  1788. assert_eq!(
  1789. program.into_bytes(),
  1790. &[0x7c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1791. );
  1792. }
  1793. #[test]
  1794. fn move_mod_from_register_to_register() {
  1795. let mut program = BpfCode::new();
  1796. program
  1797. .modulo(Source::Reg, Arch::X32)
  1798. .set_dst(0x01)
  1799. .set_src(0x02)
  1800. .push();
  1801. assert_eq!(
  1802. program.into_bytes(),
  1803. &[0x9c, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1804. );
  1805. }
  1806. #[test]
  1807. fn move_bit_xor_from_register_to_register() {
  1808. let mut program = BpfCode::new();
  1809. program
  1810. .bit_xor(Source::Reg, Arch::X32)
  1811. .set_dst(0x02)
  1812. .set_src(0x04)
  1813. .push();
  1814. assert_eq!(
  1815. program.into_bytes(),
  1816. &[0xac, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1817. );
  1818. }
  1819. #[test]
  1820. fn move_from_register_to_another_register() {
  1821. let mut program = BpfCode::new();
  1822. program
  1823. .mov(Source::Reg, Arch::X32)
  1824. .set_dst(0x00)
  1825. .set_src(0x01)
  1826. .push();
  1827. assert_eq!(
  1828. program.into_bytes(),
  1829. &[0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1830. );
  1831. }
  1832. #[test]
  1833. fn move_signed_right_shift_from_register_to_register() {
  1834. let mut program = BpfCode::new();
  1835. program
  1836. .signed_right_shift(Source::Reg, Arch::X32)
  1837. .set_dst(0x02)
  1838. .set_src(0x03)
  1839. .push();
  1840. assert_eq!(
  1841. program.into_bytes(),
  1842. &[0xcc, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  1843. );
  1844. }
  1845. }
  1846. }
  1847. }
  1848. #[cfg(test)]
  1849. mod programs {
  1850. use super::super::*;
  1851. #[test]
  1852. fn example_from_assembler() {
  1853. let mut program = BpfCode::new();
  1854. program
  1855. .add(Source::Imm, Arch::X64)
  1856. .set_dst(1)
  1857. .set_imm(0x605)
  1858. .push()
  1859. .mov(Source::Imm, Arch::X64)
  1860. .set_dst(2)
  1861. .set_imm(0x32)
  1862. .push()
  1863. .mov(Source::Reg, Arch::X64)
  1864. .set_src(0)
  1865. .set_dst(1)
  1866. .push()
  1867. .swap_bytes(Endian::Big)
  1868. .set_dst(0)
  1869. .set_imm(0x10)
  1870. .push()
  1871. .negate(Arch::X64)
  1872. .set_dst(2)
  1873. .push()
  1874. .exit()
  1875. .push();
  1876. let bytecode = program.into_bytes();
  1877. let ref_prog = &[
  1878. 0x07, 0x01, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0xb7, 0x02, 0x00, 0x00, 0x32, 0x00,
  1879. 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
  1880. 0x10, 0x00, 0x00, 0x00, 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00,
  1881. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1882. ];
  1883. // cargo says: "`[{integer}; 48]` cannot be formatted using `{:?}`
  1884. // because it doesn't implement `std::fmt::Debug`"
  1885. // So let's check in two steps.
  1886. assert_eq!(bytecode[..32], ref_prog[..32]);
  1887. assert_eq!(bytecode[33..], ref_prog[33..]);
  1888. }
  1889. }
  1890. }