bpf_exp.y 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /*
  2. * BPF asm code parser
  3. *
  4. * This program is free software; you can distribute it and/or modify
  5. * it under the terms of the GNU General Public License as published
  6. * by the Free Software Foundation; either version 2 of the License,
  7. * or (at your option) any later version.
  8. *
  9. * Syntax kept close to:
  10. *
  11. * Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new
  12. * architecture for user-level packet capture. In Proceedings of the
  13. * USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993
  14. * Conference Proceedings (USENIX'93). USENIX Association, Berkeley,
  15. * CA, USA, 2-2.
  16. *
  17. * Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
  18. * Licensed under the GNU General Public License, version 2.0 (GPLv2)
  19. */
  20. %{
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdint.h>
  24. #include <stdlib.h>
  25. #include <stdbool.h>
  26. #include <unistd.h>
  27. #include <errno.h>
  28. #include <assert.h>
  29. #include <linux/filter.h>
  30. #include "bpf_exp.yacc.h"
  31. enum jmp_type { JTL, JFL, JKL };
  32. extern FILE *yyin;
  33. extern int yylex(void);
  34. extern void yyerror(const char *str);
  35. extern void bpf_asm_compile(FILE *fp, bool cstyle);
  36. static void bpf_set_curr_instr(uint16_t op, uint8_t jt, uint8_t jf, uint32_t k);
  37. static void bpf_set_curr_label(char *label);
  38. static void bpf_set_jmp_label(char *label, enum jmp_type type);
  39. %}
  40. %union {
  41. char *label;
  42. uint32_t number;
  43. }
  44. %token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE
  45. %token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH
  46. %token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI
  47. %token OP_LDXI
  48. %token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE
  49. %token K_RXHASH K_CPU K_IFIDX K_VLAN_TCI K_VLAN_AVAIL K_VLAN_TPID K_POFF K_RAND
  50. %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
  51. %token number label
  52. %type <label> label
  53. %type <number> number
  54. %%
  55. prog
  56. : line
  57. | prog line
  58. ;
  59. line
  60. : instr
  61. | labelled_instr
  62. ;
  63. labelled_instr
  64. : labelled instr
  65. ;
  66. instr
  67. : ldb
  68. | ldh
  69. | ld
  70. | ldi
  71. | ldx
  72. | ldxi
  73. | st
  74. | stx
  75. | jmp
  76. | jeq
  77. | jneq
  78. | jlt
  79. | jle
  80. | jgt
  81. | jge
  82. | jset
  83. | add
  84. | sub
  85. | mul
  86. | div
  87. | mod
  88. | neg
  89. | and
  90. | or
  91. | xor
  92. | lsh
  93. | rsh
  94. | ret
  95. | tax
  96. | txa
  97. ;
  98. labelled
  99. : label ':' { bpf_set_curr_label($1); }
  100. ;
  101. ldb
  102. : OP_LDB '[' 'x' '+' number ']' {
  103. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $5); }
  104. | OP_LDB '[' '%' 'x' '+' number ']' {
  105. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $6); }
  106. | OP_LDB '[' number ']' {
  107. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, $3); }
  108. | OP_LDB K_PROTO {
  109. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  110. SKF_AD_OFF + SKF_AD_PROTOCOL); }
  111. | OP_LDB K_TYPE {
  112. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  113. SKF_AD_OFF + SKF_AD_PKTTYPE); }
  114. | OP_LDB K_IFIDX {
  115. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  116. SKF_AD_OFF + SKF_AD_IFINDEX); }
  117. | OP_LDB K_NLATTR {
  118. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  119. SKF_AD_OFF + SKF_AD_NLATTR); }
  120. | OP_LDB K_NLATTR_NEST {
  121. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  122. SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
  123. | OP_LDB K_MARK {
  124. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  125. SKF_AD_OFF + SKF_AD_MARK); }
  126. | OP_LDB K_QUEUE {
  127. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  128. SKF_AD_OFF + SKF_AD_QUEUE); }
  129. | OP_LDB K_HATYPE {
  130. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  131. SKF_AD_OFF + SKF_AD_HATYPE); }
  132. | OP_LDB K_RXHASH {
  133. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  134. SKF_AD_OFF + SKF_AD_RXHASH); }
  135. | OP_LDB K_CPU {
  136. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  137. SKF_AD_OFF + SKF_AD_CPU); }
  138. | OP_LDB K_VLAN_TCI {
  139. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  140. SKF_AD_OFF + SKF_AD_VLAN_TAG); }
  141. | OP_LDB K_VLAN_AVAIL {
  142. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  143. SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
  144. | OP_LDB K_POFF {
  145. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  146. SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
  147. | OP_LDB K_RAND {
  148. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  149. SKF_AD_OFF + SKF_AD_RANDOM); }
  150. | OP_LDB K_VLAN_TPID {
  151. bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
  152. SKF_AD_OFF + SKF_AD_VLAN_TPID); }
  153. ;
  154. ldh
  155. : OP_LDH '[' 'x' '+' number ']' {
  156. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); }
  157. | OP_LDH '[' '%' 'x' '+' number ']' {
  158. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); }
  159. | OP_LDH '[' number ']' {
  160. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); }
  161. | OP_LDH K_PROTO {
  162. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  163. SKF_AD_OFF + SKF_AD_PROTOCOL); }
  164. | OP_LDH K_TYPE {
  165. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  166. SKF_AD_OFF + SKF_AD_PKTTYPE); }
  167. | OP_LDH K_IFIDX {
  168. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  169. SKF_AD_OFF + SKF_AD_IFINDEX); }
  170. | OP_LDH K_NLATTR {
  171. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  172. SKF_AD_OFF + SKF_AD_NLATTR); }
  173. | OP_LDH K_NLATTR_NEST {
  174. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  175. SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
  176. | OP_LDH K_MARK {
  177. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  178. SKF_AD_OFF + SKF_AD_MARK); }
  179. | OP_LDH K_QUEUE {
  180. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  181. SKF_AD_OFF + SKF_AD_QUEUE); }
  182. | OP_LDH K_HATYPE {
  183. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  184. SKF_AD_OFF + SKF_AD_HATYPE); }
  185. | OP_LDH K_RXHASH {
  186. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  187. SKF_AD_OFF + SKF_AD_RXHASH); }
  188. | OP_LDH K_CPU {
  189. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  190. SKF_AD_OFF + SKF_AD_CPU); }
  191. | OP_LDH K_VLAN_TCI {
  192. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  193. SKF_AD_OFF + SKF_AD_VLAN_TAG); }
  194. | OP_LDH K_VLAN_AVAIL {
  195. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  196. SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
  197. | OP_LDH K_POFF {
  198. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  199. SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
  200. | OP_LDH K_RAND {
  201. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  202. SKF_AD_OFF + SKF_AD_RANDOM); }
  203. | OP_LDH K_VLAN_TPID {
  204. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  205. SKF_AD_OFF + SKF_AD_VLAN_TPID); }
  206. ;
  207. ldi
  208. : OP_LDI '#' number {
  209. bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
  210. | OP_LDI number {
  211. bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); }
  212. ;
  213. ld
  214. : OP_LD '#' number {
  215. bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
  216. | OP_LD K_PKT_LEN {
  217. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); }
  218. | OP_LD K_PROTO {
  219. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  220. SKF_AD_OFF + SKF_AD_PROTOCOL); }
  221. | OP_LD K_TYPE {
  222. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  223. SKF_AD_OFF + SKF_AD_PKTTYPE); }
  224. | OP_LD K_IFIDX {
  225. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  226. SKF_AD_OFF + SKF_AD_IFINDEX); }
  227. | OP_LD K_NLATTR {
  228. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  229. SKF_AD_OFF + SKF_AD_NLATTR); }
  230. | OP_LD K_NLATTR_NEST {
  231. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  232. SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
  233. | OP_LD K_MARK {
  234. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  235. SKF_AD_OFF + SKF_AD_MARK); }
  236. | OP_LD K_QUEUE {
  237. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  238. SKF_AD_OFF + SKF_AD_QUEUE); }
  239. | OP_LD K_HATYPE {
  240. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  241. SKF_AD_OFF + SKF_AD_HATYPE); }
  242. | OP_LD K_RXHASH {
  243. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  244. SKF_AD_OFF + SKF_AD_RXHASH); }
  245. | OP_LD K_CPU {
  246. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  247. SKF_AD_OFF + SKF_AD_CPU); }
  248. | OP_LD K_VLAN_TCI {
  249. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  250. SKF_AD_OFF + SKF_AD_VLAN_TAG); }
  251. | OP_LD K_VLAN_AVAIL {
  252. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  253. SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
  254. | OP_LD K_POFF {
  255. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  256. SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
  257. | OP_LD K_RAND {
  258. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  259. SKF_AD_OFF + SKF_AD_RANDOM); }
  260. | OP_LD K_VLAN_TPID {
  261. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  262. SKF_AD_OFF + SKF_AD_VLAN_TPID); }
  263. | OP_LD 'M' '[' number ']' {
  264. bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
  265. | OP_LD '[' 'x' '+' number ']' {
  266. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); }
  267. | OP_LD '[' '%' 'x' '+' number ']' {
  268. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); }
  269. | OP_LD '[' number ']' {
  270. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); }
  271. ;
  272. ldxi
  273. : OP_LDXI '#' number {
  274. bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
  275. | OP_LDXI number {
  276. bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); }
  277. ;
  278. ldx
  279. : OP_LDX '#' number {
  280. bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
  281. | OP_LDX K_PKT_LEN {
  282. bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); }
  283. | OP_LDX 'M' '[' number ']' {
  284. bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); }
  285. | OP_LDXB number '*' '(' '[' number ']' '&' number ')' {
  286. if ($2 != 4 || $9 != 0xf) {
  287. fprintf(stderr, "ldxb offset not supported!\n");
  288. exit(0);
  289. } else {
  290. bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
  291. | OP_LDX number '*' '(' '[' number ']' '&' number ')' {
  292. if ($2 != 4 || $9 != 0xf) {
  293. fprintf(stderr, "ldxb offset not supported!\n");
  294. exit(0);
  295. } else {
  296. bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
  297. ;
  298. st
  299. : OP_ST 'M' '[' number ']' {
  300. bpf_set_curr_instr(BPF_ST, 0, 0, $4); }
  301. ;
  302. stx
  303. : OP_STX 'M' '[' number ']' {
  304. bpf_set_curr_instr(BPF_STX, 0, 0, $4); }
  305. ;
  306. jmp
  307. : OP_JMP label {
  308. bpf_set_jmp_label($2, JKL);
  309. bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }
  310. ;
  311. jeq
  312. : OP_JEQ '#' number ',' label ',' label {
  313. bpf_set_jmp_label($5, JTL);
  314. bpf_set_jmp_label($7, JFL);
  315. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
  316. | OP_JEQ 'x' ',' label ',' label {
  317. bpf_set_jmp_label($4, JTL);
  318. bpf_set_jmp_label($6, JFL);
  319. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  320. | OP_JEQ '%' 'x' ',' label ',' label {
  321. bpf_set_jmp_label($5, JTL);
  322. bpf_set_jmp_label($7, JFL);
  323. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  324. | OP_JEQ '#' number ',' label {
  325. bpf_set_jmp_label($5, JTL);
  326. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
  327. | OP_JEQ 'x' ',' label {
  328. bpf_set_jmp_label($4, JTL);
  329. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  330. | OP_JEQ '%' 'x' ',' label {
  331. bpf_set_jmp_label($5, JTL);
  332. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  333. ;
  334. jneq
  335. : OP_JNEQ '#' number ',' label {
  336. bpf_set_jmp_label($5, JFL);
  337. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
  338. | OP_JNEQ 'x' ',' label {
  339. bpf_set_jmp_label($4, JFL);
  340. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  341. | OP_JNEQ '%' 'x' ',' label {
  342. bpf_set_jmp_label($5, JFL);
  343. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  344. ;
  345. jlt
  346. : OP_JLT '#' number ',' label {
  347. bpf_set_jmp_label($5, JFL);
  348. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
  349. | OP_JLT 'x' ',' label {
  350. bpf_set_jmp_label($4, JFL);
  351. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  352. | OP_JLT '%' 'x' ',' label {
  353. bpf_set_jmp_label($5, JFL);
  354. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  355. ;
  356. jle
  357. : OP_JLE '#' number ',' label {
  358. bpf_set_jmp_label($5, JFL);
  359. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
  360. | OP_JLE 'x' ',' label {
  361. bpf_set_jmp_label($4, JFL);
  362. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  363. | OP_JLE '%' 'x' ',' label {
  364. bpf_set_jmp_label($5, JFL);
  365. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  366. ;
  367. jgt
  368. : OP_JGT '#' number ',' label ',' label {
  369. bpf_set_jmp_label($5, JTL);
  370. bpf_set_jmp_label($7, JFL);
  371. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
  372. | OP_JGT 'x' ',' label ',' label {
  373. bpf_set_jmp_label($4, JTL);
  374. bpf_set_jmp_label($6, JFL);
  375. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  376. | OP_JGT '%' 'x' ',' label ',' label {
  377. bpf_set_jmp_label($5, JTL);
  378. bpf_set_jmp_label($7, JFL);
  379. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  380. | OP_JGT '#' number ',' label {
  381. bpf_set_jmp_label($5, JTL);
  382. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
  383. | OP_JGT 'x' ',' label {
  384. bpf_set_jmp_label($4, JTL);
  385. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  386. | OP_JGT '%' 'x' ',' label {
  387. bpf_set_jmp_label($5, JTL);
  388. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  389. ;
  390. jge
  391. : OP_JGE '#' number ',' label ',' label {
  392. bpf_set_jmp_label($5, JTL);
  393. bpf_set_jmp_label($7, JFL);
  394. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
  395. | OP_JGE 'x' ',' label ',' label {
  396. bpf_set_jmp_label($4, JTL);
  397. bpf_set_jmp_label($6, JFL);
  398. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  399. | OP_JGE '%' 'x' ',' label ',' label {
  400. bpf_set_jmp_label($5, JTL);
  401. bpf_set_jmp_label($7, JFL);
  402. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  403. | OP_JGE '#' number ',' label {
  404. bpf_set_jmp_label($5, JTL);
  405. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
  406. | OP_JGE 'x' ',' label {
  407. bpf_set_jmp_label($4, JTL);
  408. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  409. | OP_JGE '%' 'x' ',' label {
  410. bpf_set_jmp_label($5, JTL);
  411. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  412. ;
  413. jset
  414. : OP_JSET '#' number ',' label ',' label {
  415. bpf_set_jmp_label($5, JTL);
  416. bpf_set_jmp_label($7, JFL);
  417. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
  418. | OP_JSET 'x' ',' label ',' label {
  419. bpf_set_jmp_label($4, JTL);
  420. bpf_set_jmp_label($6, JFL);
  421. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  422. | OP_JSET '%' 'x' ',' label ',' label {
  423. bpf_set_jmp_label($5, JTL);
  424. bpf_set_jmp_label($7, JFL);
  425. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  426. | OP_JSET '#' number ',' label {
  427. bpf_set_jmp_label($5, JTL);
  428. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
  429. | OP_JSET 'x' ',' label {
  430. bpf_set_jmp_label($4, JTL);
  431. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  432. | OP_JSET '%' 'x' ',' label {
  433. bpf_set_jmp_label($5, JTL);
  434. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  435. ;
  436. add
  437. : OP_ADD '#' number {
  438. bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); }
  439. | OP_ADD 'x' {
  440. bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
  441. | OP_ADD '%' 'x' {
  442. bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
  443. ;
  444. sub
  445. : OP_SUB '#' number {
  446. bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); }
  447. | OP_SUB 'x' {
  448. bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
  449. | OP_SUB '%' 'x' {
  450. bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
  451. ;
  452. mul
  453. : OP_MUL '#' number {
  454. bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); }
  455. | OP_MUL 'x' {
  456. bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
  457. | OP_MUL '%' 'x' {
  458. bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
  459. ;
  460. div
  461. : OP_DIV '#' number {
  462. bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); }
  463. | OP_DIV 'x' {
  464. bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
  465. | OP_DIV '%' 'x' {
  466. bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
  467. ;
  468. mod
  469. : OP_MOD '#' number {
  470. bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); }
  471. | OP_MOD 'x' {
  472. bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
  473. | OP_MOD '%' 'x' {
  474. bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
  475. ;
  476. neg
  477. : OP_NEG {
  478. bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }
  479. ;
  480. and
  481. : OP_AND '#' number {
  482. bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); }
  483. | OP_AND 'x' {
  484. bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
  485. | OP_AND '%' 'x' {
  486. bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
  487. ;
  488. or
  489. : OP_OR '#' number {
  490. bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); }
  491. | OP_OR 'x' {
  492. bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
  493. | OP_OR '%' 'x' {
  494. bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
  495. ;
  496. xor
  497. : OP_XOR '#' number {
  498. bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); }
  499. | OP_XOR 'x' {
  500. bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
  501. | OP_XOR '%' 'x' {
  502. bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
  503. ;
  504. lsh
  505. : OP_LSH '#' number {
  506. bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); }
  507. | OP_LSH 'x' {
  508. bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
  509. | OP_LSH '%' 'x' {
  510. bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
  511. ;
  512. rsh
  513. : OP_RSH '#' number {
  514. bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); }
  515. | OP_RSH 'x' {
  516. bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
  517. | OP_RSH '%' 'x' {
  518. bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
  519. ;
  520. ret
  521. : OP_RET 'a' {
  522. bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
  523. | OP_RET '%' 'a' {
  524. bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
  525. | OP_RET 'x' {
  526. bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
  527. | OP_RET '%' 'x' {
  528. bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
  529. | OP_RET '#' number {
  530. bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); }
  531. ;
  532. tax
  533. : OP_TAX {
  534. bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }
  535. ;
  536. txa
  537. : OP_TXA {
  538. bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); }
  539. ;
  540. %%
  541. static int curr_instr = 0;
  542. static struct sock_filter out[BPF_MAXINSNS];
  543. static char **labels, **labels_jt, **labels_jf, **labels_k;
  544. static void bpf_assert_max(void)
  545. {
  546. if (curr_instr >= BPF_MAXINSNS) {
  547. fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS);
  548. exit(0);
  549. }
  550. }
  551. static void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf,
  552. uint32_t k)
  553. {
  554. bpf_assert_max();
  555. out[curr_instr].code = code;
  556. out[curr_instr].jt = jt;
  557. out[curr_instr].jf = jf;
  558. out[curr_instr].k = k;
  559. curr_instr++;
  560. }
  561. static void bpf_set_curr_label(char *label)
  562. {
  563. bpf_assert_max();
  564. labels[curr_instr] = label;
  565. }
  566. static void bpf_set_jmp_label(char *label, enum jmp_type type)
  567. {
  568. bpf_assert_max();
  569. switch (type) {
  570. case JTL:
  571. labels_jt[curr_instr] = label;
  572. break;
  573. case JFL:
  574. labels_jf[curr_instr] = label;
  575. break;
  576. case JKL:
  577. labels_k[curr_instr] = label;
  578. break;
  579. }
  580. }
  581. static int bpf_find_insns_offset(const char *label)
  582. {
  583. int i, max = curr_instr, ret = -ENOENT;
  584. for (i = 0; i < max; i++) {
  585. if (labels[i] && !strcmp(label, labels[i])) {
  586. ret = i;
  587. break;
  588. }
  589. }
  590. if (ret == -ENOENT) {
  591. fprintf(stderr, "no such label \'%s\'!\n", label);
  592. exit(0);
  593. }
  594. return ret;
  595. }
  596. static void bpf_stage_1_insert_insns(void)
  597. {
  598. yyparse();
  599. }
  600. static void bpf_reduce_k_jumps(void)
  601. {
  602. int i;
  603. for (i = 0; i < curr_instr; i++) {
  604. if (labels_k[i]) {
  605. int off = bpf_find_insns_offset(labels_k[i]);
  606. out[i].k = (uint32_t) (off - i - 1);
  607. }
  608. }
  609. }
  610. static void bpf_reduce_jt_jumps(void)
  611. {
  612. int i;
  613. for (i = 0; i < curr_instr; i++) {
  614. if (labels_jt[i]) {
  615. int off = bpf_find_insns_offset(labels_jt[i]);
  616. out[i].jt = (uint8_t) (off - i -1);
  617. }
  618. }
  619. }
  620. static void bpf_reduce_jf_jumps(void)
  621. {
  622. int i;
  623. for (i = 0; i < curr_instr; i++) {
  624. if (labels_jf[i]) {
  625. int off = bpf_find_insns_offset(labels_jf[i]);
  626. out[i].jf = (uint8_t) (off - i - 1);
  627. }
  628. }
  629. }
  630. static void bpf_stage_2_reduce_labels(void)
  631. {
  632. bpf_reduce_k_jumps();
  633. bpf_reduce_jt_jumps();
  634. bpf_reduce_jf_jumps();
  635. }
  636. static void bpf_pretty_print_c(void)
  637. {
  638. int i;
  639. for (i = 0; i < curr_instr; i++)
  640. printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code,
  641. out[i].jt, out[i].jf, out[i].k);
  642. }
  643. static void bpf_pretty_print(void)
  644. {
  645. int i;
  646. printf("%u,", curr_instr);
  647. for (i = 0; i < curr_instr; i++)
  648. printf("%u %u %u %u,", out[i].code,
  649. out[i].jt, out[i].jf, out[i].k);
  650. printf("\n");
  651. }
  652. static void bpf_init(void)
  653. {
  654. memset(out, 0, sizeof(out));
  655. labels = calloc(BPF_MAXINSNS, sizeof(*labels));
  656. assert(labels);
  657. labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt));
  658. assert(labels_jt);
  659. labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf));
  660. assert(labels_jf);
  661. labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k));
  662. assert(labels_k);
  663. }
  664. static void bpf_destroy_labels(void)
  665. {
  666. int i;
  667. for (i = 0; i < curr_instr; i++) {
  668. free(labels_jf[i]);
  669. free(labels_jt[i]);
  670. free(labels_k[i]);
  671. free(labels[i]);
  672. }
  673. }
  674. static void bpf_destroy(void)
  675. {
  676. bpf_destroy_labels();
  677. free(labels_jt);
  678. free(labels_jf);
  679. free(labels_k);
  680. free(labels);
  681. }
  682. void bpf_asm_compile(FILE *fp, bool cstyle)
  683. {
  684. yyin = fp;
  685. bpf_init();
  686. bpf_stage_1_insert_insns();
  687. bpf_stage_2_reduce_labels();
  688. bpf_destroy();
  689. if (cstyle)
  690. bpf_pretty_print_c();
  691. else
  692. bpf_pretty_print();
  693. if (fp != stdin)
  694. fclose(yyin);
  695. }
  696. void yyerror(const char *str)
  697. {
  698. exit(1);
  699. }