cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bpf_exp.y (16098B)


      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%{
     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_JGE
     55%token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH
     56%token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI
     57%token OP_LDXI
     58
     59%token K_PKT_LEN
     60
     61%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
     62
     63%token extension number label
     64
     65%type <label> label
     66%type <number> extension
     67%type <number> number
     68
     69%%
     70
     71prog
     72	: line
     73	| prog line
     74	;
     75
     76line
     77	: instr
     78	| labelled_instr
     79	;
     80
     81labelled_instr
     82	: labelled instr
     83	;
     84
     85instr
     86	: ldb
     87	| ldh
     88	| ld
     89	| ldi
     90	| ldx
     91	| ldxi
     92	| st
     93	| stx
     94	| jmp
     95	| jeq
     96	| jneq
     97	| jlt
     98	| jle
     99	| jgt
    100	| jge
    101	| jset
    102	| add
    103	| sub
    104	| mul
    105	| div
    106	| mod
    107	| neg
    108	| and
    109	| or
    110	| xor
    111	| lsh
    112	| rsh
    113	| ret
    114	| tax
    115	| txa
    116	;
    117
    118labelled
    119	: label ':' { bpf_set_curr_label($1); }
    120	;
    121
    122ldb
    123	: 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
    134ldh
    135	: 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
    146ldi
    147	: 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
    153ld
    154	: 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
    171ldxi
    172	: 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
    178ldx
    179	: 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
    199st
    200	: OP_ST 'M' '[' number ']' {
    201		bpf_set_curr_instr(BPF_ST, 0, 0, $4); }
    202	;
    203
    204stx
    205	: OP_STX 'M' '[' number ']' {
    206		bpf_set_curr_instr(BPF_STX, 0, 0, $4); }
    207	;
    208
    209jmp
    210	: OP_JMP label {
    211		bpf_set_jmp_label($2, JKL);
    212		bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }
    213	;
    214
    215jeq
    216	: 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
    239jneq
    240	: 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
    251jlt
    252	: 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
    263jle
    264	: 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
    275jgt
    276	: 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
    299jge
    300	: 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
    323jset
    324	: 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
    347add
    348	: 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
    356sub
    357	: 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
    365mul
    366	: 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
    374div
    375	: 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
    383mod
    384	: 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
    392neg
    393	: OP_NEG {
    394		bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }
    395	;
    396
    397and
    398	: 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
    406or
    407	: 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
    415xor
    416	: 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
    424lsh
    425	: 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
    433rsh
    434	: 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
    442ret
    443	: 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
    455tax
    456	: OP_TAX {
    457		bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }
    458	;
    459
    460txa
    461	: 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	else
    658		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}