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