bpf_exp.y 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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_VLANT K_VLANP 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_VLANT {
  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_VLANP {
  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. ;
  151. ldh
  152. : OP_LDH '[' 'x' '+' number ']' {
  153. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); }
  154. | OP_LDH '[' '%' 'x' '+' number ']' {
  155. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); }
  156. | OP_LDH '[' number ']' {
  157. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); }
  158. | OP_LDH K_PROTO {
  159. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  160. SKF_AD_OFF + SKF_AD_PROTOCOL); }
  161. | OP_LDH K_TYPE {
  162. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  163. SKF_AD_OFF + SKF_AD_PKTTYPE); }
  164. | OP_LDH K_IFIDX {
  165. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  166. SKF_AD_OFF + SKF_AD_IFINDEX); }
  167. | OP_LDH K_NLATTR {
  168. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  169. SKF_AD_OFF + SKF_AD_NLATTR); }
  170. | OP_LDH K_NLATTR_NEST {
  171. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  172. SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
  173. | OP_LDH K_MARK {
  174. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  175. SKF_AD_OFF + SKF_AD_MARK); }
  176. | OP_LDH K_QUEUE {
  177. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  178. SKF_AD_OFF + SKF_AD_QUEUE); }
  179. | OP_LDH K_HATYPE {
  180. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  181. SKF_AD_OFF + SKF_AD_HATYPE); }
  182. | OP_LDH K_RXHASH {
  183. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  184. SKF_AD_OFF + SKF_AD_RXHASH); }
  185. | OP_LDH K_CPU {
  186. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  187. SKF_AD_OFF + SKF_AD_CPU); }
  188. | OP_LDH K_VLANT {
  189. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  190. SKF_AD_OFF + SKF_AD_VLAN_TAG); }
  191. | OP_LDH K_VLANP {
  192. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  193. SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
  194. | OP_LDH K_POFF {
  195. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  196. SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
  197. | OP_LDH K_RAND {
  198. bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
  199. SKF_AD_OFF + SKF_AD_RANDOM); }
  200. ;
  201. ldi
  202. : OP_LDI '#' number {
  203. bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
  204. | OP_LDI number {
  205. bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); }
  206. ;
  207. ld
  208. : OP_LD '#' number {
  209. bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
  210. | OP_LD K_PKT_LEN {
  211. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); }
  212. | OP_LD K_PROTO {
  213. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  214. SKF_AD_OFF + SKF_AD_PROTOCOL); }
  215. | OP_LD K_TYPE {
  216. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  217. SKF_AD_OFF + SKF_AD_PKTTYPE); }
  218. | OP_LD K_IFIDX {
  219. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  220. SKF_AD_OFF + SKF_AD_IFINDEX); }
  221. | OP_LD K_NLATTR {
  222. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  223. SKF_AD_OFF + SKF_AD_NLATTR); }
  224. | OP_LD K_NLATTR_NEST {
  225. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  226. SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
  227. | OP_LD K_MARK {
  228. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  229. SKF_AD_OFF + SKF_AD_MARK); }
  230. | OP_LD K_QUEUE {
  231. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  232. SKF_AD_OFF + SKF_AD_QUEUE); }
  233. | OP_LD K_HATYPE {
  234. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  235. SKF_AD_OFF + SKF_AD_HATYPE); }
  236. | OP_LD K_RXHASH {
  237. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  238. SKF_AD_OFF + SKF_AD_RXHASH); }
  239. | OP_LD K_CPU {
  240. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  241. SKF_AD_OFF + SKF_AD_CPU); }
  242. | OP_LD K_VLANT {
  243. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  244. SKF_AD_OFF + SKF_AD_VLAN_TAG); }
  245. | OP_LD K_VLANP {
  246. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  247. SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
  248. | OP_LD K_POFF {
  249. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  250. SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
  251. | OP_LD K_RAND {
  252. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
  253. SKF_AD_OFF + SKF_AD_RANDOM); }
  254. | OP_LD 'M' '[' number ']' {
  255. bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
  256. | OP_LD '[' 'x' '+' number ']' {
  257. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); }
  258. | OP_LD '[' '%' 'x' '+' number ']' {
  259. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); }
  260. | OP_LD '[' number ']' {
  261. bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); }
  262. ;
  263. ldxi
  264. : OP_LDXI '#' number {
  265. bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
  266. | OP_LDXI number {
  267. bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); }
  268. ;
  269. ldx
  270. : OP_LDX '#' number {
  271. bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
  272. | OP_LDX K_PKT_LEN {
  273. bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); }
  274. | OP_LDX 'M' '[' number ']' {
  275. bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); }
  276. | OP_LDXB number '*' '(' '[' number ']' '&' number ')' {
  277. if ($2 != 4 || $9 != 0xf) {
  278. fprintf(stderr, "ldxb offset not supported!\n");
  279. exit(0);
  280. } else {
  281. bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
  282. | OP_LDX number '*' '(' '[' number ']' '&' number ')' {
  283. if ($2 != 4 || $9 != 0xf) {
  284. fprintf(stderr, "ldxb offset not supported!\n");
  285. exit(0);
  286. } else {
  287. bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
  288. ;
  289. st
  290. : OP_ST 'M' '[' number ']' {
  291. bpf_set_curr_instr(BPF_ST, 0, 0, $4); }
  292. ;
  293. stx
  294. : OP_STX 'M' '[' number ']' {
  295. bpf_set_curr_instr(BPF_STX, 0, 0, $4); }
  296. ;
  297. jmp
  298. : OP_JMP label {
  299. bpf_set_jmp_label($2, JKL);
  300. bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }
  301. ;
  302. jeq
  303. : OP_JEQ '#' number ',' label ',' label {
  304. bpf_set_jmp_label($5, JTL);
  305. bpf_set_jmp_label($7, JFL);
  306. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
  307. | OP_JEQ 'x' ',' label ',' label {
  308. bpf_set_jmp_label($4, JTL);
  309. bpf_set_jmp_label($6, JFL);
  310. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  311. | OP_JEQ '%' 'x' ',' label ',' label {
  312. bpf_set_jmp_label($5, JTL);
  313. bpf_set_jmp_label($7, JFL);
  314. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  315. | OP_JEQ '#' number ',' label {
  316. bpf_set_jmp_label($5, JTL);
  317. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
  318. | OP_JEQ 'x' ',' label {
  319. bpf_set_jmp_label($4, JTL);
  320. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  321. | OP_JEQ '%' 'x' ',' label {
  322. bpf_set_jmp_label($5, JTL);
  323. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  324. ;
  325. jneq
  326. : OP_JNEQ '#' number ',' label {
  327. bpf_set_jmp_label($5, JFL);
  328. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
  329. | OP_JNEQ 'x' ',' label {
  330. bpf_set_jmp_label($4, JFL);
  331. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  332. | OP_JNEQ '%' 'x' ',' label {
  333. bpf_set_jmp_label($5, JFL);
  334. bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
  335. ;
  336. jlt
  337. : OP_JLT '#' number ',' label {
  338. bpf_set_jmp_label($5, JFL);
  339. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
  340. | OP_JLT 'x' ',' label {
  341. bpf_set_jmp_label($4, JFL);
  342. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  343. | OP_JLT '%' 'x' ',' label {
  344. bpf_set_jmp_label($5, JFL);
  345. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  346. ;
  347. jle
  348. : OP_JLE '#' number ',' label {
  349. bpf_set_jmp_label($5, JFL);
  350. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
  351. | OP_JLE 'x' ',' label {
  352. bpf_set_jmp_label($4, JFL);
  353. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  354. | OP_JLE '%' 'x' ',' label {
  355. bpf_set_jmp_label($5, JFL);
  356. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  357. ;
  358. jgt
  359. : OP_JGT '#' number ',' label ',' label {
  360. bpf_set_jmp_label($5, JTL);
  361. bpf_set_jmp_label($7, JFL);
  362. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
  363. | OP_JGT 'x' ',' label ',' label {
  364. bpf_set_jmp_label($4, JTL);
  365. bpf_set_jmp_label($6, JFL);
  366. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  367. | OP_JGT '%' 'x' ',' label ',' label {
  368. bpf_set_jmp_label($5, JTL);
  369. bpf_set_jmp_label($7, JFL);
  370. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  371. | OP_JGT '#' number ',' label {
  372. bpf_set_jmp_label($5, JTL);
  373. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
  374. | OP_JGT 'x' ',' label {
  375. bpf_set_jmp_label($4, JTL);
  376. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  377. | OP_JGT '%' 'x' ',' label {
  378. bpf_set_jmp_label($5, JTL);
  379. bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
  380. ;
  381. jge
  382. : OP_JGE '#' number ',' label ',' label {
  383. bpf_set_jmp_label($5, JTL);
  384. bpf_set_jmp_label($7, JFL);
  385. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
  386. | OP_JGE 'x' ',' label ',' label {
  387. bpf_set_jmp_label($4, JTL);
  388. bpf_set_jmp_label($6, JFL);
  389. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  390. | OP_JGE '%' 'x' ',' label ',' label {
  391. bpf_set_jmp_label($5, JTL);
  392. bpf_set_jmp_label($7, JFL);
  393. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  394. | OP_JGE '#' number ',' label {
  395. bpf_set_jmp_label($5, JTL);
  396. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
  397. | OP_JGE 'x' ',' label {
  398. bpf_set_jmp_label($4, JTL);
  399. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  400. | OP_JGE '%' 'x' ',' label {
  401. bpf_set_jmp_label($5, JTL);
  402. bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
  403. ;
  404. jset
  405. : OP_JSET '#' number ',' label ',' label {
  406. bpf_set_jmp_label($5, JTL);
  407. bpf_set_jmp_label($7, JFL);
  408. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
  409. | OP_JSET 'x' ',' label ',' label {
  410. bpf_set_jmp_label($4, JTL);
  411. bpf_set_jmp_label($6, JFL);
  412. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  413. | OP_JSET '%' 'x' ',' label ',' label {
  414. bpf_set_jmp_label($5, JTL);
  415. bpf_set_jmp_label($7, JFL);
  416. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  417. | OP_JSET '#' number ',' label {
  418. bpf_set_jmp_label($5, JTL);
  419. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
  420. | OP_JSET 'x' ',' label {
  421. bpf_set_jmp_label($4, JTL);
  422. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  423. | OP_JSET '%' 'x' ',' label {
  424. bpf_set_jmp_label($5, JTL);
  425. bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
  426. ;
  427. add
  428. : OP_ADD '#' number {
  429. bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); }
  430. | OP_ADD 'x' {
  431. bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
  432. | OP_ADD '%' 'x' {
  433. bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
  434. ;
  435. sub
  436. : OP_SUB '#' number {
  437. bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); }
  438. | OP_SUB 'x' {
  439. bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
  440. | OP_SUB '%' 'x' {
  441. bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
  442. ;
  443. mul
  444. : OP_MUL '#' number {
  445. bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); }
  446. | OP_MUL 'x' {
  447. bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
  448. | OP_MUL '%' 'x' {
  449. bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
  450. ;
  451. div
  452. : OP_DIV '#' number {
  453. bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); }
  454. | OP_DIV 'x' {
  455. bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
  456. | OP_DIV '%' 'x' {
  457. bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
  458. ;
  459. mod
  460. : OP_MOD '#' number {
  461. bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); }
  462. | OP_MOD 'x' {
  463. bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
  464. | OP_MOD '%' 'x' {
  465. bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
  466. ;
  467. neg
  468. : OP_NEG {
  469. bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }
  470. ;
  471. and
  472. : OP_AND '#' number {
  473. bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); }
  474. | OP_AND 'x' {
  475. bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
  476. | OP_AND '%' 'x' {
  477. bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
  478. ;
  479. or
  480. : OP_OR '#' number {
  481. bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); }
  482. | OP_OR 'x' {
  483. bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
  484. | OP_OR '%' 'x' {
  485. bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
  486. ;
  487. xor
  488. : OP_XOR '#' number {
  489. bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); }
  490. | OP_XOR 'x' {
  491. bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
  492. | OP_XOR '%' 'x' {
  493. bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
  494. ;
  495. lsh
  496. : OP_LSH '#' number {
  497. bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); }
  498. | OP_LSH 'x' {
  499. bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
  500. | OP_LSH '%' 'x' {
  501. bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
  502. ;
  503. rsh
  504. : OP_RSH '#' number {
  505. bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); }
  506. | OP_RSH 'x' {
  507. bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
  508. | OP_RSH '%' 'x' {
  509. bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
  510. ;
  511. ret
  512. : OP_RET 'a' {
  513. bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
  514. | OP_RET '%' 'a' {
  515. bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
  516. | OP_RET 'x' {
  517. bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
  518. | OP_RET '%' 'x' {
  519. bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
  520. | OP_RET '#' number {
  521. bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); }
  522. ;
  523. tax
  524. : OP_TAX {
  525. bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }
  526. ;
  527. txa
  528. : OP_TXA {
  529. bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); }
  530. ;
  531. %%
  532. static int curr_instr = 0;
  533. static struct sock_filter out[BPF_MAXINSNS];
  534. static char **labels, **labels_jt, **labels_jf, **labels_k;
  535. static void bpf_assert_max(void)
  536. {
  537. if (curr_instr >= BPF_MAXINSNS) {
  538. fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS);
  539. exit(0);
  540. }
  541. }
  542. static void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf,
  543. uint32_t k)
  544. {
  545. bpf_assert_max();
  546. out[curr_instr].code = code;
  547. out[curr_instr].jt = jt;
  548. out[curr_instr].jf = jf;
  549. out[curr_instr].k = k;
  550. curr_instr++;
  551. }
  552. static void bpf_set_curr_label(char *label)
  553. {
  554. bpf_assert_max();
  555. labels[curr_instr] = label;
  556. }
  557. static void bpf_set_jmp_label(char *label, enum jmp_type type)
  558. {
  559. bpf_assert_max();
  560. switch (type) {
  561. case JTL:
  562. labels_jt[curr_instr] = label;
  563. break;
  564. case JFL:
  565. labels_jf[curr_instr] = label;
  566. break;
  567. case JKL:
  568. labels_k[curr_instr] = label;
  569. break;
  570. }
  571. }
  572. static int bpf_find_insns_offset(const char *label)
  573. {
  574. int i, max = curr_instr, ret = -ENOENT;
  575. for (i = 0; i < max; i++) {
  576. if (labels[i] && !strcmp(label, labels[i])) {
  577. ret = i;
  578. break;
  579. }
  580. }
  581. if (ret == -ENOENT) {
  582. fprintf(stderr, "no such label \'%s\'!\n", label);
  583. exit(0);
  584. }
  585. return ret;
  586. }
  587. static void bpf_stage_1_insert_insns(void)
  588. {
  589. yyparse();
  590. }
  591. static void bpf_reduce_k_jumps(void)
  592. {
  593. int i;
  594. for (i = 0; i < curr_instr; i++) {
  595. if (labels_k[i]) {
  596. int off = bpf_find_insns_offset(labels_k[i]);
  597. out[i].k = (uint32_t) (off - i - 1);
  598. }
  599. }
  600. }
  601. static void bpf_reduce_jt_jumps(void)
  602. {
  603. int i;
  604. for (i = 0; i < curr_instr; i++) {
  605. if (labels_jt[i]) {
  606. int off = bpf_find_insns_offset(labels_jt[i]);
  607. out[i].jt = (uint8_t) (off - i -1);
  608. }
  609. }
  610. }
  611. static void bpf_reduce_jf_jumps(void)
  612. {
  613. int i;
  614. for (i = 0; i < curr_instr; i++) {
  615. if (labels_jf[i]) {
  616. int off = bpf_find_insns_offset(labels_jf[i]);
  617. out[i].jf = (uint8_t) (off - i - 1);
  618. }
  619. }
  620. }
  621. static void bpf_stage_2_reduce_labels(void)
  622. {
  623. bpf_reduce_k_jumps();
  624. bpf_reduce_jt_jumps();
  625. bpf_reduce_jf_jumps();
  626. }
  627. static void bpf_pretty_print_c(void)
  628. {
  629. int i;
  630. for (i = 0; i < curr_instr; i++)
  631. printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code,
  632. out[i].jt, out[i].jf, out[i].k);
  633. }
  634. static void bpf_pretty_print(void)
  635. {
  636. int i;
  637. printf("%u,", curr_instr);
  638. for (i = 0; i < curr_instr; i++)
  639. printf("%u %u %u %u,", out[i].code,
  640. out[i].jt, out[i].jf, out[i].k);
  641. printf("\n");
  642. }
  643. static void bpf_init(void)
  644. {
  645. memset(out, 0, sizeof(out));
  646. labels = calloc(BPF_MAXINSNS, sizeof(*labels));
  647. assert(labels);
  648. labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt));
  649. assert(labels_jt);
  650. labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf));
  651. assert(labels_jf);
  652. labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k));
  653. assert(labels_k);
  654. }
  655. static void bpf_destroy_labels(void)
  656. {
  657. int i;
  658. for (i = 0; i < curr_instr; i++) {
  659. free(labels_jf[i]);
  660. free(labels_jt[i]);
  661. free(labels_k[i]);
  662. free(labels[i]);
  663. }
  664. }
  665. static void bpf_destroy(void)
  666. {
  667. bpf_destroy_labels();
  668. free(labels_jt);
  669. free(labels_jf);
  670. free(labels_k);
  671. free(labels);
  672. }
  673. void bpf_asm_compile(FILE *fp, bool cstyle)
  674. {
  675. yyin = fp;
  676. bpf_init();
  677. bpf_stage_1_insert_insns();
  678. bpf_stage_2_reduce_labels();
  679. bpf_destroy();
  680. if (cstyle)
  681. bpf_pretty_print_c();
  682. else
  683. bpf_pretty_print();
  684. if (fp != stdin)
  685. fclose(yyin);
  686. }
  687. void yyerror(const char *str)
  688. {
  689. exit(1);
  690. }