disassembler.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
  2. // Copyright 2017 Jan-Erik Rediger <badboy@archlinux.us>
  3. //
  4. // Adopted from tests in `tests/assembler.rs`
  5. extern crate rbpf;
  6. mod common;
  7. use rbpf::assembler::assemble;
  8. use rbpf::disassembler::to_insn_vec;
  9. // Using a macro to keep actual line numbers in failure output
  10. macro_rules! disasm {
  11. ($src:expr) => {
  12. {
  13. let src = $src;
  14. let asm = assemble(src).expect("Can't assemble from string");
  15. let insn = to_insn_vec(&asm);
  16. let reasm = insn.into_iter().map(|ins| ins.desc).collect::<Vec<_>>().join("\n");
  17. assert_eq!(src, reasm);
  18. }
  19. }
  20. }
  21. #[test]
  22. fn test_empty() {
  23. disasm!("");
  24. }
  25. // Example for InstructionType::NoOperand.
  26. #[test]
  27. fn test_exit() {
  28. disasm!("exit");
  29. }
  30. // Example for InstructionType::AluBinary.
  31. #[test]
  32. fn test_add64() {
  33. disasm!("add64 r1, r3");
  34. disasm!("add64 r1, 0x5");
  35. }
  36. // Example for InstructionType::AluUnary.
  37. #[test]
  38. fn test_neg64() {
  39. disasm!("neg64 r1");
  40. }
  41. // Example for InstructionType::LoadReg.
  42. #[test]
  43. fn test_ldxw() {
  44. disasm!("ldxw r1, [r2+0x5]");
  45. }
  46. // Example for InstructionType::StoreImm.
  47. #[test]
  48. fn test_stw() {
  49. disasm!("stw [r2+0x5], 0x7");
  50. }
  51. // Example for InstructionType::StoreReg.
  52. #[test]
  53. fn test_stxw() {
  54. disasm!("stxw [r2+0x5], r8");
  55. }
  56. // Example for InstructionType::JumpUnconditional.
  57. #[test]
  58. fn test_ja() {
  59. disasm!("ja +0x8");
  60. }
  61. // Example for InstructionType::JumpConditional.
  62. #[test]
  63. fn test_jeq() {
  64. disasm!("jeq r1, 0x4, +0x8");
  65. disasm!("jeq r1, r3, +0x8");
  66. }
  67. // Example for InstructionType::Call.
  68. #[test]
  69. fn test_call() {
  70. disasm!("call 0x3");
  71. }
  72. // Example for InstructionType::Endian.
  73. #[test]
  74. fn test_be32() {
  75. disasm!("be32 r1");
  76. }
  77. // Example for InstructionType::LoadImm.
  78. #[test]
  79. fn test_lddw() {
  80. disasm!("lddw r1, 0x1234abcd5678eeff");
  81. disasm!("lddw r1, 0xff11ee22dd33cc44");
  82. }
  83. // Example for InstructionType::LoadAbs.
  84. #[test]
  85. fn test_ldabsw() {
  86. disasm!("ldabsw 0x1");
  87. }
  88. // Example for InstructionType::LoadInd.
  89. #[test]
  90. fn test_ldindw() {
  91. disasm!("ldindw r1, 0x2");
  92. }
  93. // Example for InstructionType::LoadReg.
  94. #[test]
  95. fn test_ldxdw() {
  96. disasm!("ldxdw r1, [r2+0x3]");
  97. }
  98. // Example for InstructionType::StoreImm.
  99. #[test]
  100. fn test_sth() {
  101. disasm!("sth [r1+0x2], 0x3");
  102. }
  103. // Example for InstructionType::StoreReg.
  104. #[test]
  105. fn test_stxh() {
  106. disasm!("stxh [r1+0x2], r3");
  107. }
  108. // Test all supported AluBinary mnemonics.
  109. #[test]
  110. fn test_alu_binary() {
  111. disasm!("add64 r1, r2
  112. sub64 r1, r2
  113. mul64 r1, r2
  114. div64 r1, r2
  115. or64 r1, r2
  116. and64 r1, r2
  117. lsh64 r1, r2
  118. rsh64 r1, r2
  119. mod64 r1, r2
  120. xor64 r1, r2
  121. mov64 r1, r2
  122. arsh64 r1, r2");
  123. disasm!("add64 r1, 0x2
  124. sub64 r1, 0x2
  125. mul64 r1, 0x2
  126. div64 r1, 0x2
  127. or64 r1, 0x2
  128. and64 r1, 0x2
  129. lsh64 r1, 0x2
  130. rsh64 r1, 0x2
  131. mod64 r1, 0x2
  132. xor64 r1, 0x2
  133. mov64 r1, 0x2
  134. arsh64 r1, 0x2");
  135. disasm!("add32 r1, r2
  136. sub32 r1, r2
  137. mul32 r1, r2
  138. div32 r1, r2
  139. or32 r1, r2
  140. and32 r1, r2
  141. lsh32 r1, r2
  142. rsh32 r1, r2
  143. mod32 r1, r2
  144. xor32 r1, r2
  145. mov32 r1, r2
  146. arsh32 r1, r2");
  147. disasm!("add32 r1, 0x2
  148. sub32 r1, 0x2
  149. mul32 r1, 0x2
  150. div32 r1, 0x2
  151. or32 r1, 0x2
  152. and32 r1, 0x2
  153. lsh32 r1, 0x2
  154. rsh32 r1, 0x2
  155. mod32 r1, 0x2
  156. xor32 r1, 0x2
  157. mov32 r1, 0x2
  158. arsh32 r1, 0x2");
  159. }
  160. // Test all supported AluUnary mnemonics.
  161. #[test]
  162. fn test_alu_unary() {
  163. disasm!("neg64 r1
  164. neg32 r1");
  165. }
  166. // Test all supported LoadAbs mnemonics.
  167. #[test]
  168. fn test_load_abs() {
  169. disasm!("ldabsw 0x1
  170. ldabsh 0x1
  171. ldabsb 0x1
  172. ldabsdw 0x1");
  173. }
  174. // Test all supported LoadInd mnemonics.
  175. #[test]
  176. fn test_load_ind() {
  177. disasm!("ldindw r1, 0x2
  178. ldindh r1, 0x2
  179. ldindb r1, 0x2
  180. ldinddw r1, 0x2");
  181. }
  182. // Test all supported LoadReg mnemonics.
  183. #[test]
  184. fn test_load_reg() {
  185. disasm!(r"ldxw r1, [r2+0x3]
  186. ldxh r1, [r2+0x3]
  187. ldxb r1, [r2+0x3]
  188. ldxdw r1, [r2+0x3]");
  189. }
  190. // Test all supported StoreImm mnemonics.
  191. #[test]
  192. fn test_store_imm() {
  193. disasm!("stw [r1+0x2], 0x3
  194. sth [r1+0x2], 0x3
  195. stb [r1+0x2], 0x3
  196. stdw [r1+0x2], 0x3");
  197. }
  198. // Test all supported StoreReg mnemonics.
  199. #[test]
  200. fn test_store_reg() {
  201. disasm!("stxw [r1+0x2], r3
  202. stxh [r1+0x2], r3
  203. stxb [r1+0x2], r3
  204. stxdw [r1+0x2], r3");
  205. }
  206. // Test all supported JumpConditional mnemonics.
  207. #[test]
  208. fn test_jump_conditional() {
  209. disasm!("jeq r1, r2, +0x3
  210. jgt r1, r2, +0x3
  211. jge r1, r2, +0x3
  212. jlt r1, r2, +0x3
  213. jle r1, r2, +0x3
  214. jset r1, r2, +0x3
  215. jne r1, r2, +0x3
  216. jsgt r1, r2, +0x3
  217. jsge r1, r2, -0x3
  218. jslt r1, r2, +0x3
  219. jsle r1, r2, -0x3");
  220. disasm!("jeq r1, 0x2, +0x3
  221. jgt r1, 0x2, +0x3
  222. jge r1, 0x2, +0x3
  223. jlt r1, 0x2, +0x3
  224. jle r1, 0x2, +0x3
  225. jset r1, 0x2, +0x3
  226. jne r1, 0x2, +0x3
  227. jsgt r1, 0x2, +0x3
  228. jsge r1, 0x2, -0x3
  229. jslt r1, 0x2, +0x3
  230. jsle r1, 0x2, -0x3");
  231. }
  232. // Test all supported Endian mnemonics.
  233. #[test]
  234. fn test_endian() {
  235. disasm!("be16 r1
  236. be32 r1
  237. be64 r1
  238. le16 r1
  239. le32 r1
  240. le64 r1");
  241. }
  242. #[test]
  243. fn test_large_immediate() {
  244. disasm!("add64 r1, 0x7fffffff");
  245. disasm!("add64 r1, 0x7fffffff");
  246. }