4
0

disassembler.rs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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.trim().lines().map(|l| l.trim()).collect::<Vec<_>>().join("\n");
  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!("
  112. add64 r1, r2
  113. sub64 r1, r2
  114. mul64 r1, r2
  115. div64 r1, r2
  116. or64 r1, r2
  117. and64 r1, r2
  118. lsh64 r1, r2
  119. rsh64 r1, r2
  120. mod64 r1, r2
  121. xor64 r1, r2
  122. mov64 r1, r2
  123. arsh64 r1, r2
  124. ");
  125. disasm!("
  126. add64 r1, 0x2
  127. sub64 r1, 0x2
  128. mul64 r1, 0x2
  129. div64 r1, 0x2
  130. or64 r1, 0x2
  131. and64 r1, 0x2
  132. lsh64 r1, 0x2
  133. rsh64 r1, 0x2
  134. mod64 r1, 0x2
  135. xor64 r1, 0x2
  136. mov64 r1, 0x2
  137. arsh64 r1, 0x2
  138. ");
  139. disasm!("
  140. add32 r1, r2
  141. sub32 r1, r2
  142. mul32 r1, r2
  143. div32 r1, r2
  144. or32 r1, r2
  145. and32 r1, r2
  146. lsh32 r1, r2
  147. rsh32 r1, r2
  148. mod32 r1, r2
  149. xor32 r1, r2
  150. mov32 r1, r2
  151. arsh32 r1, r2
  152. ");
  153. disasm!("
  154. add32 r1, 0x2
  155. sub32 r1, 0x2
  156. mul32 r1, 0x2
  157. div32 r1, 0x2
  158. or32 r1, 0x2
  159. and32 r1, 0x2
  160. lsh32 r1, 0x2
  161. rsh32 r1, 0x2
  162. mod32 r1, 0x2
  163. xor32 r1, 0x2
  164. mov32 r1, 0x2
  165. arsh32 r1, 0x2
  166. ");
  167. }
  168. // Test all supported AluUnary mnemonics.
  169. #[test]
  170. fn test_alu_unary() {
  171. disasm!("
  172. neg64 r1
  173. neg32 r1
  174. ");
  175. }
  176. // Test all supported LoadAbs mnemonics.
  177. #[test]
  178. fn test_load_abs() {
  179. disasm!("
  180. ldabsw 0x1
  181. ldabsh 0x1
  182. ldabsb 0x1
  183. ldabsdw 0x1
  184. ");
  185. }
  186. // Test all supported LoadInd mnemonics.
  187. #[test]
  188. fn test_load_ind() {
  189. disasm!("
  190. ldindw r1, 0x2
  191. ldindh r1, 0x2
  192. ldindb r1, 0x2
  193. ldinddw r1, 0x2
  194. ");
  195. }
  196. // Test all supported LoadReg mnemonics.
  197. #[test]
  198. fn test_load_reg() {
  199. disasm!(r"
  200. ldxw r1, [r2+0x3]
  201. ldxh r1, [r2+0x3]
  202. ldxb r1, [r2+0x3]
  203. ldxdw r1, [r2+0x3]
  204. ");
  205. }
  206. // Test all supported StoreImm mnemonics.
  207. #[test]
  208. fn test_store_imm() {
  209. disasm!("
  210. stw [r1+0x2], 0x3
  211. sth [r1+0x2], 0x3
  212. stb [r1+0x2], 0x3
  213. stdw [r1+0x2], 0x3
  214. ");
  215. }
  216. // Test all supported StoreReg mnemonics.
  217. #[test]
  218. fn test_store_reg() {
  219. disasm!("
  220. stxw [r1+0x2], r3
  221. stxh [r1+0x2], r3
  222. stxb [r1+0x2], r3
  223. stxdw [r1+0x2], r3
  224. ");
  225. }
  226. // Test all supported JumpConditional mnemonics.
  227. #[test]
  228. fn test_jump_conditional() {
  229. disasm!("
  230. jeq r1, r2, +0x3
  231. jgt r1, r2, +0x3
  232. jge r1, r2, +0x3
  233. jlt r1, r2, +0x3
  234. jle r1, r2, +0x3
  235. jset r1, r2, +0x3
  236. jne r1, r2, +0x3
  237. jsgt r1, r2, +0x3
  238. jsge r1, r2, -0x3
  239. jslt r1, r2, +0x3
  240. jsle r1, r2, -0x3
  241. ");
  242. disasm!("
  243. jeq r1, 0x2, +0x3
  244. jgt r1, 0x2, +0x3
  245. jge r1, 0x2, +0x3
  246. jlt r1, 0x2, +0x3
  247. jle r1, 0x2, +0x3
  248. jset r1, 0x2, +0x3
  249. jne r1, 0x2, +0x3
  250. jsgt r1, 0x2, +0x3
  251. jsge r1, 0x2, -0x3
  252. jslt r1, 0x2, +0x3
  253. jsle r1, 0x2, -0x3
  254. ");
  255. disasm!("
  256. jeq32 r1, r2, +0x3
  257. jgt32 r1, r2, +0x3
  258. jge32 r1, r2, +0x3
  259. jlt32 r1, r2, +0x3
  260. jle32 r1, r2, +0x3
  261. jset32 r1, r2, +0x3
  262. jne32 r1, r2, +0x3
  263. jsgt32 r1, r2, +0x3
  264. jsge32 r1, r2, -0x3
  265. jslt32 r1, r2, +0x3
  266. jsle32 r1, r2, -0x3
  267. ");
  268. disasm!("
  269. jeq32 r1, 0x2, +0x3
  270. jgt32 r1, 0x2, +0x3
  271. jge32 r1, 0x2, +0x3
  272. jlt32 r1, 0x2, +0x3
  273. jle32 r1, 0x2, +0x3
  274. jset32 r1, 0x2, +0x3
  275. jne32 r1, 0x2, +0x3
  276. jsgt32 r1, 0x2, +0x3
  277. jsge32 r1, 0x2, -0x3
  278. jslt32 r1, 0x2, +0x3
  279. jsle32 r1, 0x2, -0x3
  280. ");
  281. }
  282. // Test all supported Endian mnemonics.
  283. #[test]
  284. fn test_endian() {
  285. disasm!("
  286. be16 r1
  287. be32 r1
  288. be64 r1
  289. le16 r1
  290. le32 r1
  291. le64 r1
  292. ");
  293. }
  294. #[test]
  295. fn test_large_immediate() {
  296. disasm!("add64 r1, 0x7fffffff");
  297. disasm!("add64 r1, 0x7fffffff");
  298. }
  299. // Non-regression tests for overflow when trying to negate offset 0x8000i16.
  300. #[test]
  301. fn test_offset_overflow() {
  302. #[rustfmt::skip]
  303. let insns = [
  304. 0x62, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stw
  305. 0x6a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // sth
  306. 0x72, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stb
  307. 0x7a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stdw
  308. 0x61, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxw
  309. 0x69, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxh
  310. 0x71, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxb
  311. 0x79, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxdw
  312. 0x15, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq (imm)
  313. 0x1d, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq (reg)
  314. 0x16, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq32 (imm)
  315. 0x1e, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq32 (reg)
  316. ];
  317. let expected_output = "
  318. stw [r1-0x8000], 0x1
  319. sth [r1-0x8000], 0x1
  320. stb [r1-0x8000], 0x1
  321. stdw [r1-0x8000], 0x1
  322. ldxw r1, [r0-0x8000]
  323. ldxh r1, [r0-0x8000]
  324. ldxb r1, [r0-0x8000]
  325. ldxdw r1, [r0-0x8000]
  326. jeq r1, 0x2, -0x8000
  327. jeq r1, r2, -0x8000
  328. jeq32 r1, 0x2, -0x8000
  329. jeq32 r1, r2, -0x8000
  330. ".trim().lines().map(|l| l.trim()).collect::<Vec<_>>().join("\n");
  331. let prog = to_insn_vec(&insns);
  332. let asm = prog.into_iter().map(|ins| ins.desc).collect::<Vec<_>>().join("\n");
  333. assert_eq!(asm, expected_output);
  334. }