bpf_exp.y 19 KB

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