asm_parser.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // Copyright 2017 Rich Lane <lanerl@gmail.com>
  2. //
  3. // Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
  4. // the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
  5. // copied, modified, or distributed except according to those terms.
  6. extern crate rbpf;
  7. extern crate combine;
  8. use rbpf::asm_parser::{Instruction, Operand, parse};
  9. #[test]
  10. fn test_empty() {
  11. assert_eq!(parse(""), Ok(vec![]));
  12. }
  13. #[test]
  14. fn test_exit() {
  15. // No operands.
  16. assert_eq!(parse("exit"),
  17. Ok(vec![Instruction {
  18. name: "exit".to_string(),
  19. operands: vec![],
  20. }]));
  21. }
  22. #[test]
  23. fn test_lsh() {
  24. // Register and immediate operands.
  25. assert_eq!(parse("lsh r3, 0x20"),
  26. Ok(vec![Instruction {
  27. name: "lsh".to_string(),
  28. operands: vec![Operand::Register(3), Operand::Integer(0x20)],
  29. }]));
  30. }
  31. #[test]
  32. fn test_ja() {
  33. // Jump offset operand.
  34. assert_eq!(parse("ja +1"),
  35. Ok(vec![Instruction {
  36. name: "ja".to_string(),
  37. operands: vec![Operand::Integer(1)],
  38. }]));
  39. }
  40. #[test]
  41. fn test_ldxh() {
  42. // Register and memory operands.
  43. assert_eq!(parse("ldxh r4, [r1+12]"),
  44. Ok(vec![Instruction {
  45. name: "ldxh".to_string(),
  46. operands: vec![Operand::Register(4), Operand::Memory(1, 12)],
  47. }]));
  48. }
  49. #[test]
  50. fn test_tcp_sack() {
  51. // Sample program from ubpf.
  52. let src = "\
  53. ldxb r2, [r1+12]
  54. ldxb r3, [r1+13]
  55. lsh r3, 0x8
  56. or r3, r2
  57. mov r0, 0x0
  58. jne r3, 0x8, +37
  59. ldxb r2, [r1+23]
  60. jne r2, 0x6, +35
  61. ldxb r2, [r1+14]
  62. add r1, 0xe
  63. and r2, 0xf
  64. lsh r2, 0x2
  65. add r1, r2
  66. mov r0, 0x0
  67. ldxh r4, [r1+12]
  68. add r1, 0x14
  69. rsh r4, 0x2
  70. and r4, 0x3c
  71. mov r2, r4
  72. add r2, 0xffffffec
  73. mov r5, 0x15
  74. mov r3, 0x0
  75. jgt r5, r4, +20
  76. mov r5, r3
  77. lsh r5, 0x20
  78. arsh r5, 0x20
  79. mov r4, r1
  80. add r4, r5
  81. ldxb r5, [r4]
  82. jeq r5, 0x1, +4
  83. jeq r5, 0x0, +12
  84. mov r6, r3
  85. jeq r5, 0x5, +9
  86. ja +2
  87. add r3, 0x1
  88. mov r6, r3
  89. ldxb r3, [r4+1]
  90. add r3, r6
  91. lsh r3, 0x20
  92. arsh r3, 0x20
  93. jsgt r2, r3, -18
  94. ja +1
  95. mov r0, 0x1
  96. exit
  97. ";
  98. assert_eq!(parse(src),
  99. Ok(vec![Instruction {
  100. name: "ldxb".to_string(),
  101. operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
  102. },
  103. Instruction {
  104. name: "ldxb".to_string(),
  105. operands: vec![Operand::Register(3), Operand::Memory(1, 13)],
  106. },
  107. Instruction {
  108. name: "lsh".to_string(),
  109. operands: vec![Operand::Register(3), Operand::Integer(8)],
  110. },
  111. Instruction {
  112. name: "or".to_string(),
  113. operands: vec![Operand::Register(3), Operand::Register(2)],
  114. },
  115. Instruction {
  116. name: "mov".to_string(),
  117. operands: vec![Operand::Register(0), Operand::Integer(0)],
  118. },
  119. Instruction {
  120. name: "jne".to_string(),
  121. operands: vec![Operand::Register(3),
  122. Operand::Integer(8),
  123. Operand::Integer(37)],
  124. },
  125. Instruction {
  126. name: "ldxb".to_string(),
  127. operands: vec![Operand::Register(2), Operand::Memory(1, 23)],
  128. },
  129. Instruction {
  130. name: "jne".to_string(),
  131. operands: vec![Operand::Register(2),
  132. Operand::Integer(6),
  133. Operand::Integer(35)],
  134. },
  135. Instruction {
  136. name: "ldxb".to_string(),
  137. operands: vec![Operand::Register(2), Operand::Memory(1, 14)],
  138. },
  139. Instruction {
  140. name: "add".to_string(),
  141. operands: vec![Operand::Register(1), Operand::Integer(14)],
  142. },
  143. Instruction {
  144. name: "and".to_string(),
  145. operands: vec![Operand::Register(2), Operand::Integer(15)],
  146. },
  147. Instruction {
  148. name: "lsh".to_string(),
  149. operands: vec![Operand::Register(2), Operand::Integer(2)],
  150. },
  151. Instruction {
  152. name: "add".to_string(),
  153. operands: vec![Operand::Register(1), Operand::Register(2)],
  154. },
  155. Instruction {
  156. name: "mov".to_string(),
  157. operands: vec![Operand::Register(0), Operand::Integer(0)],
  158. },
  159. Instruction {
  160. name: "ldxh".to_string(),
  161. operands: vec![Operand::Register(4), Operand::Memory(1, 12)],
  162. },
  163. Instruction {
  164. name: "add".to_string(),
  165. operands: vec![Operand::Register(1), Operand::Integer(20)],
  166. },
  167. Instruction {
  168. name: "rsh".to_string(),
  169. operands: vec![Operand::Register(4), Operand::Integer(2)],
  170. },
  171. Instruction {
  172. name: "and".to_string(),
  173. operands: vec![Operand::Register(4), Operand::Integer(60)],
  174. },
  175. Instruction {
  176. name: "mov".to_string(),
  177. operands: vec![Operand::Register(2), Operand::Register(4)],
  178. },
  179. Instruction {
  180. name: "add".to_string(),
  181. operands: vec![Operand::Register(2), Operand::Integer(4294967276)],
  182. },
  183. Instruction {
  184. name: "mov".to_string(),
  185. operands: vec![Operand::Register(5), Operand::Integer(21)],
  186. },
  187. Instruction {
  188. name: "mov".to_string(),
  189. operands: vec![Operand::Register(3), Operand::Integer(0)],
  190. },
  191. Instruction {
  192. name: "jgt".to_string(),
  193. operands: vec![Operand::Register(5),
  194. Operand::Register(4),
  195. Operand::Integer(20)],
  196. },
  197. Instruction {
  198. name: "mov".to_string(),
  199. operands: vec![Operand::Register(5), Operand::Register(3)],
  200. },
  201. Instruction {
  202. name: "lsh".to_string(),
  203. operands: vec![Operand::Register(5), Operand::Integer(32)],
  204. },
  205. Instruction {
  206. name: "arsh".to_string(),
  207. operands: vec![Operand::Register(5), Operand::Integer(32)],
  208. },
  209. Instruction {
  210. name: "mov".to_string(),
  211. operands: vec![Operand::Register(4), Operand::Register(1)],
  212. },
  213. Instruction {
  214. name: "add".to_string(),
  215. operands: vec![Operand::Register(4), Operand::Register(5)],
  216. },
  217. Instruction {
  218. name: "ldxb".to_string(),
  219. operands: vec![Operand::Register(5), Operand::Memory(4, 0)],
  220. },
  221. Instruction {
  222. name: "jeq".to_string(),
  223. operands: vec![Operand::Register(5),
  224. Operand::Integer(1),
  225. Operand::Integer(4)],
  226. },
  227. Instruction {
  228. name: "jeq".to_string(),
  229. operands: vec![Operand::Register(5),
  230. Operand::Integer(0),
  231. Operand::Integer(12)],
  232. },
  233. Instruction {
  234. name: "mov".to_string(),
  235. operands: vec![Operand::Register(6), Operand::Register(3)],
  236. },
  237. Instruction {
  238. name: "jeq".to_string(),
  239. operands: vec![Operand::Register(5),
  240. Operand::Integer(5),
  241. Operand::Integer(9)],
  242. },
  243. Instruction {
  244. name: "ja".to_string(),
  245. operands: vec![Operand::Integer(2)],
  246. },
  247. Instruction {
  248. name: "add".to_string(),
  249. operands: vec![Operand::Register(3), Operand::Integer(1)],
  250. },
  251. Instruction {
  252. name: "mov".to_string(),
  253. operands: vec![Operand::Register(6), Operand::Register(3)],
  254. },
  255. Instruction {
  256. name: "ldxb".to_string(),
  257. operands: vec![Operand::Register(3), Operand::Memory(4, 1)],
  258. },
  259. Instruction {
  260. name: "add".to_string(),
  261. operands: vec![Operand::Register(3), Operand::Register(6)],
  262. },
  263. Instruction {
  264. name: "lsh".to_string(),
  265. operands: vec![Operand::Register(3), Operand::Integer(32)],
  266. },
  267. Instruction {
  268. name: "arsh".to_string(),
  269. operands: vec![Operand::Register(3), Operand::Integer(32)],
  270. },
  271. Instruction {
  272. name: "jsgt".to_string(),
  273. operands: vec![Operand::Register(2),
  274. Operand::Register(3),
  275. Operand::Integer(-18)],
  276. },
  277. Instruction {
  278. name: "ja".to_string(),
  279. operands: vec![Operand::Integer(1)],
  280. },
  281. Instruction {
  282. name: "mov".to_string(),
  283. operands: vec![Operand::Register(0), Operand::Integer(1)],
  284. },
  285. Instruction {
  286. name: "exit".to_string(),
  287. operands: vec![],
  288. }]));
  289. }
  290. #[test]
  291. fn test_error_eof() {
  292. // Unexpected end of input in a register name.
  293. assert_eq!(parse("lsh r"),
  294. Err("Parse error at line 1 column 6: unexpected end of input, expected digit"
  295. .to_string()));
  296. }
  297. #[test]
  298. fn test_error_unexpected_character() {
  299. // Unexpected character at end of input.
  300. assert_eq!(parse("exit\n^"),
  301. Err("Parse error at line 2 column 1: unexpected '^', expected end of input"
  302. .to_string()));
  303. }