asm_parser.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. }
  304. #[test]
  305. fn test_initial_whitespace() {
  306. assert_eq!(parse("
  307. exit"),
  308. Ok(vec![Instruction {
  309. name: "exit".to_string(),
  310. operands: vec![],
  311. }]));
  312. }