4
0

disassembler.rs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  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. let src = $src
  13. .trim()
  14. .lines()
  15. .map(|l| l.trim())
  16. .collect::<Vec<_>>()
  17. .join("\n");
  18. let asm = assemble(&src).expect("Can't assemble from string");
  19. let insn = to_insn_vec(&asm);
  20. let reasm = insn
  21. .into_iter()
  22. .map(|ins| ins.desc)
  23. .collect::<Vec<_>>()
  24. .join("\n");
  25. assert_eq!(src, reasm);
  26. }};
  27. }
  28. #[test]
  29. fn test_empty() {
  30. disasm!("");
  31. }
  32. // Example for InstructionType::NoOperand.
  33. #[test]
  34. fn test_exit() {
  35. disasm!("exit");
  36. }
  37. // Example for InstructionType::AluBinary.
  38. #[test]
  39. fn test_add64() {
  40. disasm!("add64 r1, r3");
  41. disasm!("add64 r1, 0x5");
  42. }
  43. // Example for InstructionType::AluUnary.
  44. #[test]
  45. fn test_neg64() {
  46. disasm!("neg64 r1");
  47. }
  48. // Example for InstructionType::LoadReg.
  49. #[test]
  50. fn test_ldxw() {
  51. disasm!("ldxw r1, [r2+0x5]");
  52. }
  53. // Example for InstructionType::StoreImm.
  54. #[test]
  55. fn test_stw() {
  56. disasm!("stw [r2+0x5], 0x7");
  57. }
  58. // Example for InstructionType::StoreReg.
  59. #[test]
  60. fn test_stxw() {
  61. disasm!("stxw [r2+0x5], r8");
  62. }
  63. // Example for InstructionType::JumpUnconditional.
  64. #[test]
  65. fn test_ja() {
  66. disasm!("ja +0x8");
  67. }
  68. // Example for InstructionType::JumpConditional.
  69. #[test]
  70. fn test_jeq() {
  71. disasm!("jeq r1, 0x4, +0x8");
  72. disasm!("jeq r1, r3, +0x8");
  73. }
  74. // Example for InstructionType::Call.
  75. #[test]
  76. fn test_call() {
  77. disasm!("call 0x3");
  78. }
  79. // Example for InstructionType::Endian.
  80. #[test]
  81. fn test_be32() {
  82. disasm!("be32 r1");
  83. }
  84. // Example for InstructionType::LoadImm.
  85. #[test]
  86. fn test_lddw() {
  87. disasm!("lddw r1, 0x1234abcd5678eeff");
  88. disasm!("lddw r1, 0xff11ee22dd33cc44");
  89. }
  90. // Example for InstructionType::LoadAbs.
  91. #[test]
  92. fn test_ldabsw() {
  93. disasm!("ldabsw 0x1");
  94. }
  95. // Example for InstructionType::LoadInd.
  96. #[test]
  97. fn test_ldindw() {
  98. disasm!("ldindw r1, 0x2");
  99. }
  100. // Example for InstructionType::LoadReg.
  101. #[test]
  102. fn test_ldxdw() {
  103. disasm!("ldxdw r1, [r2+0x3]");
  104. }
  105. // Example for InstructionType::StoreImm.
  106. #[test]
  107. fn test_sth() {
  108. disasm!("sth [r1+0x2], 0x3");
  109. }
  110. // Example for InstructionType::StoreReg.
  111. #[test]
  112. fn test_stxh() {
  113. disasm!("stxh [r1+0x2], r3");
  114. }
  115. // Test all supported AluBinary mnemonics.
  116. #[test]
  117. fn test_alu_binary() {
  118. disasm!(
  119. "
  120. add64 r1, r2
  121. sub64 r1, r2
  122. mul64 r1, r2
  123. div64 r1, r2
  124. or64 r1, r2
  125. and64 r1, r2
  126. lsh64 r1, r2
  127. rsh64 r1, r2
  128. mod64 r1, r2
  129. xor64 r1, r2
  130. mov64 r1, r2
  131. arsh64 r1, r2
  132. "
  133. );
  134. disasm!(
  135. "
  136. add64 r1, 0x2
  137. sub64 r1, 0x2
  138. mul64 r1, 0x2
  139. div64 r1, 0x2
  140. or64 r1, 0x2
  141. and64 r1, 0x2
  142. lsh64 r1, 0x2
  143. rsh64 r1, 0x2
  144. mod64 r1, 0x2
  145. xor64 r1, 0x2
  146. mov64 r1, 0x2
  147. arsh64 r1, 0x2
  148. "
  149. );
  150. disasm!(
  151. "
  152. add32 r1, r2
  153. sub32 r1, r2
  154. mul32 r1, r2
  155. div32 r1, r2
  156. or32 r1, r2
  157. and32 r1, r2
  158. lsh32 r1, r2
  159. rsh32 r1, r2
  160. mod32 r1, r2
  161. xor32 r1, r2
  162. mov32 r1, r2
  163. arsh32 r1, r2
  164. "
  165. );
  166. disasm!(
  167. "
  168. add32 r1, 0x2
  169. sub32 r1, 0x2
  170. mul32 r1, 0x2
  171. div32 r1, 0x2
  172. or32 r1, 0x2
  173. and32 r1, 0x2
  174. lsh32 r1, 0x2
  175. rsh32 r1, 0x2
  176. mod32 r1, 0x2
  177. xor32 r1, 0x2
  178. mov32 r1, 0x2
  179. arsh32 r1, 0x2
  180. "
  181. );
  182. }
  183. // Test all supported AluUnary mnemonics.
  184. #[test]
  185. fn test_alu_unary() {
  186. disasm!(
  187. "
  188. neg64 r1
  189. neg32 r1
  190. "
  191. );
  192. }
  193. // Test all supported LoadAbs mnemonics.
  194. #[test]
  195. fn test_load_abs() {
  196. disasm!(
  197. "
  198. ldabsw 0x1
  199. ldabsh 0x1
  200. ldabsb 0x1
  201. ldabsdw 0x1
  202. "
  203. );
  204. }
  205. // Test all supported LoadInd mnemonics.
  206. #[test]
  207. fn test_load_ind() {
  208. disasm!(
  209. "
  210. ldindw r1, 0x2
  211. ldindh r1, 0x2
  212. ldindb r1, 0x2
  213. ldinddw r1, 0x2
  214. "
  215. );
  216. }
  217. // Test all supported LoadReg mnemonics.
  218. #[test]
  219. fn test_load_reg() {
  220. disasm!(
  221. r"
  222. ldxw r1, [r2+0x3]
  223. ldxh r1, [r2+0x3]
  224. ldxb r1, [r2+0x3]
  225. ldxdw r1, [r2+0x3]
  226. "
  227. );
  228. }
  229. // Test all supported StoreImm mnemonics.
  230. #[test]
  231. fn test_store_imm() {
  232. disasm!(
  233. "
  234. stw [r1+0x2], 0x3
  235. sth [r1+0x2], 0x3
  236. stb [r1+0x2], 0x3
  237. stdw [r1+0x2], 0x3
  238. "
  239. );
  240. }
  241. // Test all supported StoreReg mnemonics.
  242. #[test]
  243. fn test_store_reg() {
  244. disasm!(
  245. "
  246. stxw [r1+0x2], r3
  247. stxh [r1+0x2], r3
  248. stxb [r1+0x2], r3
  249. stxdw [r1+0x2], r3
  250. "
  251. );
  252. }
  253. // Test all supported JumpConditional mnemonics.
  254. #[test]
  255. fn test_jump_conditional() {
  256. disasm!(
  257. "
  258. jeq r1, r2, +0x3
  259. jgt r1, r2, +0x3
  260. jge r1, r2, +0x3
  261. jlt r1, r2, +0x3
  262. jle r1, r2, +0x3
  263. jset r1, r2, +0x3
  264. jne r1, r2, +0x3
  265. jsgt r1, r2, +0x3
  266. jsge r1, r2, -0x3
  267. jslt r1, r2, +0x3
  268. jsle r1, r2, -0x3
  269. "
  270. );
  271. disasm!(
  272. "
  273. jeq r1, 0x2, +0x3
  274. jgt r1, 0x2, +0x3
  275. jge r1, 0x2, +0x3
  276. jlt r1, 0x2, +0x3
  277. jle r1, 0x2, +0x3
  278. jset r1, 0x2, +0x3
  279. jne r1, 0x2, +0x3
  280. jsgt r1, 0x2, +0x3
  281. jsge r1, 0x2, -0x3
  282. jslt r1, 0x2, +0x3
  283. jsle r1, 0x2, -0x3
  284. "
  285. );
  286. disasm!(
  287. "
  288. jeq32 r1, r2, +0x3
  289. jgt32 r1, r2, +0x3
  290. jge32 r1, r2, +0x3
  291. jlt32 r1, r2, +0x3
  292. jle32 r1, r2, +0x3
  293. jset32 r1, r2, +0x3
  294. jne32 r1, r2, +0x3
  295. jsgt32 r1, r2, +0x3
  296. jsge32 r1, r2, -0x3
  297. jslt32 r1, r2, +0x3
  298. jsle32 r1, r2, -0x3
  299. "
  300. );
  301. disasm!(
  302. "
  303. jeq32 r1, 0x2, +0x3
  304. jgt32 r1, 0x2, +0x3
  305. jge32 r1, 0x2, +0x3
  306. jlt32 r1, 0x2, +0x3
  307. jle32 r1, 0x2, +0x3
  308. jset32 r1, 0x2, +0x3
  309. jne32 r1, 0x2, +0x3
  310. jsgt32 r1, 0x2, +0x3
  311. jsge32 r1, 0x2, -0x3
  312. jslt32 r1, 0x2, +0x3
  313. jsle32 r1, 0x2, -0x3
  314. "
  315. );
  316. }
  317. // Test all supported Endian mnemonics.
  318. #[test]
  319. fn test_endian() {
  320. disasm!(
  321. "
  322. be16 r1
  323. be32 r1
  324. be64 r1
  325. le16 r1
  326. le32 r1
  327. le64 r1
  328. "
  329. );
  330. }
  331. #[test]
  332. fn test_large_immediate() {
  333. disasm!("add64 r1, 0x7fffffff");
  334. disasm!("add64 r1, 0x7fffffff");
  335. }
  336. // Non-regression tests for overflow when trying to negate offset 0x8000i16.
  337. #[test]
  338. fn test_offset_overflow() {
  339. #[rustfmt::skip]
  340. let insns = [
  341. 0x62, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stw
  342. 0x6a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // sth
  343. 0x72, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stb
  344. 0x7a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stdw
  345. 0x61, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxw
  346. 0x69, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxh
  347. 0x71, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxb
  348. 0x79, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxdw
  349. 0x15, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq (imm)
  350. 0x1d, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq (reg)
  351. 0x16, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq32 (imm)
  352. 0x1e, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq32 (reg)
  353. ];
  354. let expected_output = "
  355. stw [r1-0x8000], 0x1
  356. sth [r1-0x8000], 0x1
  357. stb [r1-0x8000], 0x1
  358. stdw [r1-0x8000], 0x1
  359. ldxw r1, [r0-0x8000]
  360. ldxh r1, [r0-0x8000]
  361. ldxb r1, [r0-0x8000]
  362. ldxdw r1, [r0-0x8000]
  363. jeq r1, 0x2, -0x8000
  364. jeq r1, r2, -0x8000
  365. jeq32 r1, 0x2, -0x8000
  366. jeq32 r1, r2, -0x8000
  367. "
  368. .trim()
  369. .lines()
  370. .map(|l| l.trim())
  371. .collect::<Vec<_>>()
  372. .join("\n");
  373. let prog = to_insn_vec(&insns);
  374. let asm = prog
  375. .into_iter()
  376. .map(|ins| ins.desc)
  377. .collect::<Vec<_>>()
  378. .join("\n");
  379. assert_eq!(asm, expected_output);
  380. }