brintos

brintos / linux-shallow public Read only

0
0
Text · 15.7 KiB · dfb7254 Raw
669 lines · plain
1/*2 * BPF asm code parser3 *4 * This program is free software; you can distribute it and/or modify5 * it under the terms of the GNU General Public License as published6 * 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 new12 * architecture for user-level packet capture. In Proceedings of the13 * USENIX Winter 1993 Conference Proceedings on USENIX Winter 199314 * 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%{22 23#include <stdio.h>24#include <string.h>25#include <stdint.h>26#include <stdlib.h>27#include <stdbool.h>28#include <unistd.h>29#include <errno.h>30#include <assert.h>31#include <linux/filter.h>32 33#include "bpf_exp.yacc.h"34 35enum jmp_type { JTL, JFL, JKL };36 37extern FILE *yyin;38extern int yylineno;39extern int yylex(void);40extern void yyerror(const char *str);41 42extern void bpf_asm_compile(FILE *fp, bool cstyle);43static void bpf_set_curr_instr(uint16_t op, uint8_t jt, uint8_t jf, uint32_t k);44static void bpf_set_curr_label(char *label);45static void bpf_set_jmp_label(char *label, enum jmp_type type);46 47%}48 49%union {50	char *label;51	uint32_t number;52}53 54%token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE55%token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH56%token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI57%token OP_LDXI58 59%token K_PKT_LEN60 61%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'62 63%token extension number label64 65%type <label> label66%type <number> extension67%type <number> number68 69%%70 71prog72	: line73	| prog line74	;75 76line77	: instr78	| labelled_instr79	;80 81labelled_instr82	: labelled instr83	;84 85instr86	: ldb87	| ldh88	| ld89	| ldi90	| ldx91	| ldxi92	| st93	| stx94	| jmp95	| jeq96	| jneq97	| jlt98	| jle99	| jgt100	| jge101	| jset102	| add103	| sub104	| mul105	| div106	| mod107	| neg108	| and109	| or110	| xor111	| lsh112	| rsh113	| ret114	| tax115	| txa116	;117 118labelled119	: label ':' { bpf_set_curr_label($1); }120	;121 122ldb123	: OP_LDB '[' 'x' '+' number ']' {124		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $5); }125	| OP_LDB '[' '%' 'x' '+' number ']' {126		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $6); }127	| OP_LDB '[' number ']' {128		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, $3); }129	| OP_LDB extension {130		bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,131				   SKF_AD_OFF + $2); }132	;133 134ldh135	: OP_LDH '[' 'x' '+' number ']' {136		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); }137	| OP_LDH '[' '%' 'x' '+' number ']' {138		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); }139	| OP_LDH '[' number ']' {140		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); }141	| OP_LDH extension {142		bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,143				   SKF_AD_OFF + $2); }144	;145 146ldi147	: OP_LDI '#' number {148		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }149	| OP_LDI number {150		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); }151	;152 153ld154	: OP_LD '#' number {155		bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }156	| OP_LD K_PKT_LEN {157		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); }158	| OP_LD extension {159		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,160				   SKF_AD_OFF + $2); }161	| OP_LD 'M' '[' number ']' {162		bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }163	| OP_LD '[' 'x' '+' number ']' {164		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); }165	| OP_LD '[' '%' 'x' '+' number ']' {166		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); }167	| OP_LD '[' number ']' {168		bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); }169	;170 171ldxi172	: OP_LDXI '#' number {173		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }174	| OP_LDXI number {175		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); }176	;177 178ldx179	: OP_LDX '#' number {180		bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }181	| OP_LDX K_PKT_LEN {182		bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); }183	| OP_LDX 'M' '[' number ']' {184		bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); }185	| OP_LDXB number '*' '(' '[' number ']' '&' number ')' {186		if ($2 != 4 || $9 != 0xf) {187			fprintf(stderr, "ldxb offset not supported!\n");188			exit(1);189		} else {190			bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }191	| OP_LDX number '*' '(' '[' number ']' '&' number ')' {192		if ($2 != 4 || $9 != 0xf) {193			fprintf(stderr, "ldxb offset not supported!\n");194			exit(1);195		} else {196			bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }197	;198 199st200	: OP_ST 'M' '[' number ']' {201		bpf_set_curr_instr(BPF_ST, 0, 0, $4); }202	;203 204stx205	: OP_STX 'M' '[' number ']' {206		bpf_set_curr_instr(BPF_STX, 0, 0, $4); }207	;208 209jmp210	: OP_JMP label {211		bpf_set_jmp_label($2, JKL);212		bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }213	;214 215jeq216	: OP_JEQ '#' number ',' label ',' label {217		bpf_set_jmp_label($5, JTL);218		bpf_set_jmp_label($7, JFL);219		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }220	| OP_JEQ 'x' ',' label ',' label {221		bpf_set_jmp_label($4, JTL);222		bpf_set_jmp_label($6, JFL);223		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }224	| OP_JEQ '%' 'x' ',' label ',' label {225		bpf_set_jmp_label($5, JTL);226		bpf_set_jmp_label($7, JFL);227		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }228	| OP_JEQ '#' number ',' label {229		bpf_set_jmp_label($5, JTL);230		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }231	| OP_JEQ 'x' ',' label {232		bpf_set_jmp_label($4, JTL);233		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }234	| OP_JEQ '%' 'x' ',' label {235		bpf_set_jmp_label($5, JTL);236		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }237	;238 239jneq240	: OP_JNEQ '#' number ',' label {241		bpf_set_jmp_label($5, JFL);242		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }243	| OP_JNEQ 'x' ',' label {244		bpf_set_jmp_label($4, JFL);245		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }246	| OP_JNEQ '%' 'x' ',' label {247		bpf_set_jmp_label($5, JFL);248		bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }249	;250 251jlt252	: OP_JLT '#' number ',' label {253		bpf_set_jmp_label($5, JFL);254		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }255	| OP_JLT 'x' ',' label {256		bpf_set_jmp_label($4, JFL);257		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }258	| OP_JLT '%' 'x' ',' label {259		bpf_set_jmp_label($5, JFL);260		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }261	;262 263jle264	: OP_JLE '#' number ',' label {265		bpf_set_jmp_label($5, JFL);266		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }267	| OP_JLE 'x' ',' label {268		bpf_set_jmp_label($4, JFL);269		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }270	| OP_JLE '%' 'x' ',' label {271		bpf_set_jmp_label($5, JFL);272		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }273	;274 275jgt276	: OP_JGT '#' number ',' label ',' label {277		bpf_set_jmp_label($5, JTL);278		bpf_set_jmp_label($7, JFL);279		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }280	| OP_JGT 'x' ',' label ',' label {281		bpf_set_jmp_label($4, JTL);282		bpf_set_jmp_label($6, JFL);283		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }284	| OP_JGT '%' 'x' ',' label ',' label {285		bpf_set_jmp_label($5, JTL);286		bpf_set_jmp_label($7, JFL);287		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }288	| OP_JGT '#' number ',' label {289		bpf_set_jmp_label($5, JTL);290		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }291	| OP_JGT 'x' ',' label {292		bpf_set_jmp_label($4, JTL);293		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }294	| OP_JGT '%' 'x' ',' label {295		bpf_set_jmp_label($5, JTL);296		bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }297	;298 299jge300	: OP_JGE '#' number ',' label ',' label {301		bpf_set_jmp_label($5, JTL);302		bpf_set_jmp_label($7, JFL);303		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }304	| OP_JGE 'x' ',' label ',' label {305		bpf_set_jmp_label($4, JTL);306		bpf_set_jmp_label($6, JFL);307		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }308	| OP_JGE '%' 'x' ',' label ',' label {309		bpf_set_jmp_label($5, JTL);310		bpf_set_jmp_label($7, JFL);311		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }312	| OP_JGE '#' number ',' label {313		bpf_set_jmp_label($5, JTL);314		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }315	| OP_JGE 'x' ',' label {316		bpf_set_jmp_label($4, JTL);317		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }318	| OP_JGE '%' 'x' ',' label {319		bpf_set_jmp_label($5, JTL);320		bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }321	;322 323jset324	: OP_JSET '#' number ',' label ',' label {325		bpf_set_jmp_label($5, JTL);326		bpf_set_jmp_label($7, JFL);327		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }328	| OP_JSET 'x' ',' label ',' label {329		bpf_set_jmp_label($4, JTL);330		bpf_set_jmp_label($6, JFL);331		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }332	| OP_JSET '%' 'x' ',' label ',' label {333		bpf_set_jmp_label($5, JTL);334		bpf_set_jmp_label($7, JFL);335		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }336	| OP_JSET '#' number ',' label {337		bpf_set_jmp_label($5, JTL);338		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }339	| OP_JSET 'x' ',' label {340		bpf_set_jmp_label($4, JTL);341		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }342	| OP_JSET '%' 'x' ',' label {343		bpf_set_jmp_label($5, JTL);344		bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }345	;346 347add348	: OP_ADD '#' number {349		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); }350	| OP_ADD 'x' {351		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }352	| OP_ADD '%' 'x' {353		bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }354	;355 356sub357	: OP_SUB '#' number {358		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); }359	| OP_SUB 'x' {360		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }361	| OP_SUB '%' 'x' {362		bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }363	;364 365mul366	: OP_MUL '#' number {367		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); }368	| OP_MUL 'x' {369		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }370	| OP_MUL '%' 'x' {371		bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }372	;373 374div375	: OP_DIV '#' number {376		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); }377	| OP_DIV 'x' {378		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }379	| OP_DIV '%' 'x' {380		bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }381	;382 383mod384	: OP_MOD '#' number {385		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); }386	| OP_MOD 'x' {387		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }388	| OP_MOD '%' 'x' {389		bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }390	;391 392neg393	: OP_NEG {394		bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }395	;396 397and398	: OP_AND '#' number {399		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); }400	| OP_AND 'x' {401		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }402	| OP_AND '%' 'x' {403		bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }404	;405 406or407	: OP_OR '#' number {408		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); }409	| OP_OR 'x' {410		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }411	| OP_OR '%' 'x' {412		bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }413	;414 415xor416	: OP_XOR '#' number {417		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); }418	| OP_XOR 'x' {419		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }420	| OP_XOR '%' 'x' {421		bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }422	;423 424lsh425	: OP_LSH '#' number {426		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); }427	| OP_LSH 'x' {428		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }429	| OP_LSH '%' 'x' {430		bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }431	;432 433rsh434	: OP_RSH '#' number {435		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); }436	| OP_RSH 'x' {437		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }438	| OP_RSH '%' 'x' {439		bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }440	;441 442ret443	: OP_RET 'a' {444		bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }445	| OP_RET '%' 'a' {446		bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }447	| OP_RET 'x' {448		bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }449	| OP_RET '%' 'x' {450		bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }451	| OP_RET '#' number {452		bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); }453	;454 455tax456	: OP_TAX {457		bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }458	;459 460txa461	: OP_TXA {462		bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); }463	;464 465%%466 467static int curr_instr = 0;468static struct sock_filter out[BPF_MAXINSNS];469static char **labels, **labels_jt, **labels_jf, **labels_k;470 471static void bpf_assert_max(void)472{473	if (curr_instr >= BPF_MAXINSNS) {474		fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS);475		exit(1);476	}477}478 479static void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf,480			       uint32_t k)481{482	bpf_assert_max();483	out[curr_instr].code = code;484	out[curr_instr].jt = jt;485	out[curr_instr].jf = jf;486	out[curr_instr].k = k;487	curr_instr++;488}489 490static void bpf_set_curr_label(char *label)491{492	bpf_assert_max();493	labels[curr_instr] = label;494}495 496static void bpf_set_jmp_label(char *label, enum jmp_type type)497{498	bpf_assert_max();499	switch (type) {500	case JTL:501		labels_jt[curr_instr] = label;502		break;503	case JFL:504		labels_jf[curr_instr] = label;505		break;506	case JKL:507		labels_k[curr_instr] = label;508		break;509	}510}511 512static int bpf_find_insns_offset(const char *label)513{514	int i, max = curr_instr, ret = -ENOENT;515 516	for (i = 0; i < max; i++) {517		if (labels[i] && !strcmp(label, labels[i])) {518			ret = i;519			break;520		}521	}522 523	if (ret == -ENOENT) {524		fprintf(stderr, "no such label \'%s\'!\n", label);525		exit(1);526	}527 528	return ret;529}530 531static void bpf_stage_1_insert_insns(void)532{533	yyparse();534}535 536static void bpf_reduce_k_jumps(void)537{538	int i;539 540	for (i = 0; i < curr_instr; i++) {541		if (labels_k[i]) {542			int off = bpf_find_insns_offset(labels_k[i]);543			out[i].k = (uint32_t) (off - i - 1);544		}545	}546}547 548static uint8_t bpf_encode_jt_jf_offset(int off, int i)549{550	int delta = off - i - 1;551 552	if (delta < 0 || delta > 255) {553		fprintf(stderr, "error: insn #%d jumps to insn #%d, "554				"which is out of range\n", i, off);555		exit(1);556	}557	return (uint8_t) delta;558}559 560static void bpf_reduce_jt_jumps(void)561{562	int i;563 564	for (i = 0; i < curr_instr; i++) {565		if (labels_jt[i]) {566			int off = bpf_find_insns_offset(labels_jt[i]);567			out[i].jt = bpf_encode_jt_jf_offset(off, i);568		}569	}570}571 572static void bpf_reduce_jf_jumps(void)573{574	int i;575 576	for (i = 0; i < curr_instr; i++) {577		if (labels_jf[i]) {578			int off = bpf_find_insns_offset(labels_jf[i]);579			out[i].jf = bpf_encode_jt_jf_offset(off, i);580		}581	}582}583 584static void bpf_stage_2_reduce_labels(void)585{586	bpf_reduce_k_jumps();587	bpf_reduce_jt_jumps();588	bpf_reduce_jf_jumps();589}590 591static void bpf_pretty_print_c(void)592{593	int i;594 595	for (i = 0; i < curr_instr; i++)596		printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code,597		       out[i].jt, out[i].jf, out[i].k);598}599 600static void bpf_pretty_print(void)601{602	int i;603 604	printf("%u,", curr_instr);605	for (i = 0; i < curr_instr; i++)606		printf("%u %u %u %u,", out[i].code,607		       out[i].jt, out[i].jf, out[i].k);608	printf("\n");609}610 611static void bpf_init(void)612{613	memset(out, 0, sizeof(out));614 615	labels = calloc(BPF_MAXINSNS, sizeof(*labels));616	assert(labels);617	labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt));618	assert(labels_jt);619	labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf));620	assert(labels_jf);621	labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k));622	assert(labels_k);623}624 625static void bpf_destroy_labels(void)626{627	int i;628 629	for (i = 0; i < curr_instr; i++) {630		free(labels_jf[i]);631		free(labels_jt[i]);632		free(labels_k[i]);633		free(labels[i]);634	}635}636 637static void bpf_destroy(void)638{639	bpf_destroy_labels();640	free(labels_jt);641	free(labels_jf);642	free(labels_k);643	free(labels);644}645 646void bpf_asm_compile(FILE *fp, bool cstyle)647{648	yyin = fp;649 650	bpf_init();651	bpf_stage_1_insert_insns();652	bpf_stage_2_reduce_labels();653	bpf_destroy();654 655	if (cstyle)656		bpf_pretty_print_c();657	else658		bpf_pretty_print();659 660	if (fp != stdin)661		fclose(yyin);662}663 664void yyerror(const char *str)665{666	fprintf(stderr, "error: %s at line %d\n", str, yylineno);667	exit(1);668}669