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