Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * BPF asm code parser
0003  *
0004  * This program is free software; you can distribute it and/or modify
0005  * it under the terms of the GNU General Public License as published
0006  * by the Free Software Foundation; either version 2 of the License,
0007  * or (at your option) any later version.
0008  *
0009  * Syntax kept close to:
0010  *
0011  * Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new
0012  * architecture for user-level packet capture. In Proceedings of the
0013  * USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993
0014  * Conference Proceedings (USENIX'93). USENIX Association, Berkeley,
0015  * CA, USA, 2-2.
0016  *
0017  * Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
0018  * Licensed under the GNU General Public License, version 2.0 (GPLv2)
0019  */
0020 
0021 %{
0022 
0023 #include <stdio.h>
0024 #include <string.h>
0025 #include <stdint.h>
0026 #include <stdlib.h>
0027 #include <stdbool.h>
0028 #include <unistd.h>
0029 #include <errno.h>
0030 #include <assert.h>
0031 #include <linux/filter.h>
0032 
0033 #include "bpf_exp.yacc.h"
0034 
0035 enum jmp_type { JTL, JFL, JKL };
0036 
0037 extern FILE *yyin;
0038 extern int yylineno;
0039 extern int yylex(void);
0040 extern void yyerror(const char *str);
0041 
0042 extern void bpf_asm_compile(FILE *fp, bool cstyle);
0043 static void bpf_set_curr_instr(uint16_t op, uint8_t jt, uint8_t jf, uint32_t k);
0044 static void bpf_set_curr_label(char *label);
0045 static void bpf_set_jmp_label(char *label, enum jmp_type type);
0046 
0047 %}
0048 
0049 %union {
0050         char *label;
0051         uint32_t number;
0052 }
0053 
0054 %token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE
0055 %token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH
0056 %token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI
0057 %token OP_LDXI
0058 
0059 %token K_PKT_LEN
0060 
0061 %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
0062 
0063 %token extension number label
0064 
0065 %type <label> label
0066 %type <number> extension
0067 %type <number> number
0068 
0069 %%
0070 
0071 prog
0072         : line
0073         | prog line
0074         ;
0075 
0076 line
0077         : instr
0078         | labelled_instr
0079         ;
0080 
0081 labelled_instr
0082         : labelled instr
0083         ;
0084 
0085 instr
0086         : ldb
0087         | ldh
0088         | ld
0089         | ldi
0090         | ldx
0091         | ldxi
0092         | st
0093         | stx
0094         | jmp
0095         | jeq
0096         | jneq
0097         | jlt
0098         | jle
0099         | jgt
0100         | jge
0101         | jset
0102         | add
0103         | sub
0104         | mul
0105         | div
0106         | mod
0107         | neg
0108         | and
0109         | or
0110         | xor
0111         | lsh
0112         | rsh
0113         | ret
0114         | tax
0115         | txa
0116         ;
0117 
0118 labelled
0119         : label ':' { bpf_set_curr_label($1); }
0120         ;
0121 
0122 ldb
0123         : OP_LDB '[' 'x' '+' number ']' {
0124                 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $5); }
0125         | OP_LDB '[' '%' 'x' '+' number ']' {
0126                 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $6); }
0127         | OP_LDB '[' number ']' {
0128                 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, $3); }
0129         | OP_LDB extension {
0130                 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
0131                                    SKF_AD_OFF + $2); }
0132         ;
0133 
0134 ldh
0135         : OP_LDH '[' 'x' '+' number ']' {
0136                 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); }
0137         | OP_LDH '[' '%' 'x' '+' number ']' {
0138                 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); }
0139         | OP_LDH '[' number ']' {
0140                 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); }
0141         | OP_LDH extension {
0142                 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
0143                                    SKF_AD_OFF + $2); }
0144         ;
0145 
0146 ldi
0147         : OP_LDI '#' number {
0148                 bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
0149         | OP_LDI number {
0150                 bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); }
0151         ;
0152 
0153 ld
0154         : OP_LD '#' number {
0155                 bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
0156         | OP_LD K_PKT_LEN {
0157                 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); }
0158         | OP_LD extension {
0159                 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
0160                                    SKF_AD_OFF + $2); }
0161         | OP_LD 'M' '[' number ']' {
0162                 bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
0163         | OP_LD '[' 'x' '+' number ']' {
0164                 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); }
0165         | OP_LD '[' '%' 'x' '+' number ']' {
0166                 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); }
0167         | OP_LD '[' number ']' {
0168                 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); }
0169         ;
0170 
0171 ldxi
0172         : OP_LDXI '#' number {
0173                 bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
0174         | OP_LDXI number {
0175                 bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); }
0176         ;
0177 
0178 ldx
0179         : OP_LDX '#' number {
0180                 bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
0181         | OP_LDX K_PKT_LEN {
0182                 bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); }
0183         | OP_LDX 'M' '[' number ']' {
0184                 bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); }
0185         | OP_LDXB number '*' '(' '[' number ']' '&' number ')' {
0186                 if ($2 != 4 || $9 != 0xf) {
0187                         fprintf(stderr, "ldxb offset not supported!\n");
0188                         exit(1);
0189                 } else {
0190                         bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
0191         | OP_LDX number '*' '(' '[' number ']' '&' number ')' {
0192                 if ($2 != 4 || $9 != 0xf) {
0193                         fprintf(stderr, "ldxb offset not supported!\n");
0194                         exit(1);
0195                 } else {
0196                         bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
0197         ;
0198 
0199 st
0200         : OP_ST 'M' '[' number ']' {
0201                 bpf_set_curr_instr(BPF_ST, 0, 0, $4); }
0202         ;
0203 
0204 stx
0205         : OP_STX 'M' '[' number ']' {
0206                 bpf_set_curr_instr(BPF_STX, 0, 0, $4); }
0207         ;
0208 
0209 jmp
0210         : OP_JMP label {
0211                 bpf_set_jmp_label($2, JKL);
0212                 bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }
0213         ;
0214 
0215 jeq
0216         : OP_JEQ '#' number ',' label ',' label {
0217                 bpf_set_jmp_label($5, JTL);
0218                 bpf_set_jmp_label($7, JFL);
0219                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
0220         | OP_JEQ 'x' ',' label ',' label {
0221                 bpf_set_jmp_label($4, JTL);
0222                 bpf_set_jmp_label($6, JFL);
0223                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
0224         | OP_JEQ '%' 'x' ',' label ',' label {
0225                 bpf_set_jmp_label($5, JTL);
0226                 bpf_set_jmp_label($7, JFL);
0227                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
0228         | OP_JEQ '#' number ',' label {
0229                 bpf_set_jmp_label($5, JTL);
0230                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
0231         | OP_JEQ 'x' ',' label {
0232                 bpf_set_jmp_label($4, JTL);
0233                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
0234         | OP_JEQ '%' 'x' ',' label {
0235                 bpf_set_jmp_label($5, JTL);
0236                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
0237         ;
0238 
0239 jneq
0240         : OP_JNEQ '#' number ',' label {
0241                 bpf_set_jmp_label($5, JFL);
0242                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
0243         | OP_JNEQ 'x' ',' label {
0244                 bpf_set_jmp_label($4, JFL);
0245                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
0246         | OP_JNEQ '%' 'x' ',' label {
0247                 bpf_set_jmp_label($5, JFL);
0248                 bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
0249         ;
0250 
0251 jlt
0252         : OP_JLT '#' number ',' label {
0253                 bpf_set_jmp_label($5, JFL);
0254                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
0255         | OP_JLT 'x' ',' label {
0256                 bpf_set_jmp_label($4, JFL);
0257                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
0258         | OP_JLT '%' 'x' ',' label {
0259                 bpf_set_jmp_label($5, JFL);
0260                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
0261         ;
0262 
0263 jle
0264         : OP_JLE '#' number ',' label {
0265                 bpf_set_jmp_label($5, JFL);
0266                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
0267         | OP_JLE 'x' ',' label {
0268                 bpf_set_jmp_label($4, JFL);
0269                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
0270         | OP_JLE '%' 'x' ',' label {
0271                 bpf_set_jmp_label($5, JFL);
0272                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
0273         ;
0274 
0275 jgt
0276         : OP_JGT '#' number ',' label ',' label {
0277                 bpf_set_jmp_label($5, JTL);
0278                 bpf_set_jmp_label($7, JFL);
0279                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
0280         | OP_JGT 'x' ',' label ',' label {
0281                 bpf_set_jmp_label($4, JTL);
0282                 bpf_set_jmp_label($6, JFL);
0283                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
0284         | OP_JGT '%' 'x' ',' label ',' label {
0285                 bpf_set_jmp_label($5, JTL);
0286                 bpf_set_jmp_label($7, JFL);
0287                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
0288         | OP_JGT '#' number ',' label {
0289                 bpf_set_jmp_label($5, JTL);
0290                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
0291         | OP_JGT 'x' ',' label {
0292                 bpf_set_jmp_label($4, JTL);
0293                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
0294         | OP_JGT '%' 'x' ',' label {
0295                 bpf_set_jmp_label($5, JTL);
0296                 bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
0297         ;
0298 
0299 jge
0300         : OP_JGE '#' number ',' label ',' label {
0301                 bpf_set_jmp_label($5, JTL);
0302                 bpf_set_jmp_label($7, JFL);
0303                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
0304         | OP_JGE 'x' ',' label ',' label {
0305                 bpf_set_jmp_label($4, JTL);
0306                 bpf_set_jmp_label($6, JFL);
0307                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
0308         | OP_JGE '%' 'x' ',' label ',' label {
0309                 bpf_set_jmp_label($5, JTL);
0310                 bpf_set_jmp_label($7, JFL);
0311                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
0312         | OP_JGE '#' number ',' label {
0313                 bpf_set_jmp_label($5, JTL);
0314                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
0315         | OP_JGE 'x' ',' label {
0316                 bpf_set_jmp_label($4, JTL);
0317                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
0318         | OP_JGE '%' 'x' ',' label {
0319                 bpf_set_jmp_label($5, JTL);
0320                 bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
0321         ;
0322 
0323 jset
0324         : OP_JSET '#' number ',' label ',' label {
0325                 bpf_set_jmp_label($5, JTL);
0326                 bpf_set_jmp_label($7, JFL);
0327                 bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
0328         | OP_JSET 'x' ',' label ',' label {
0329                 bpf_set_jmp_label($4, JTL);
0330                 bpf_set_jmp_label($6, JFL);
0331                 bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
0332         | OP_JSET '%' 'x' ',' label ',' label {
0333                 bpf_set_jmp_label($5, JTL);
0334                 bpf_set_jmp_label($7, JFL);
0335                 bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
0336         | OP_JSET '#' number ',' label {
0337                 bpf_set_jmp_label($5, JTL);
0338                 bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
0339         | OP_JSET 'x' ',' label {
0340                 bpf_set_jmp_label($4, JTL);
0341                 bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
0342         | OP_JSET '%' 'x' ',' label {
0343                 bpf_set_jmp_label($5, JTL);
0344                 bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
0345         ;
0346 
0347 add
0348         : OP_ADD '#' number {
0349                 bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); }
0350         | OP_ADD 'x' {
0351                 bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
0352         | OP_ADD '%' 'x' {
0353                 bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
0354         ;
0355 
0356 sub
0357         : OP_SUB '#' number {
0358                 bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); }
0359         | OP_SUB 'x' {
0360                 bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
0361         | OP_SUB '%' 'x' {
0362                 bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
0363         ;
0364 
0365 mul
0366         : OP_MUL '#' number {
0367                 bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); }
0368         | OP_MUL 'x' {
0369                 bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
0370         | OP_MUL '%' 'x' {
0371                 bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
0372         ;
0373 
0374 div
0375         : OP_DIV '#' number {
0376                 bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); }
0377         | OP_DIV 'x' {
0378                 bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
0379         | OP_DIV '%' 'x' {
0380                 bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
0381         ;
0382 
0383 mod
0384         : OP_MOD '#' number {
0385                 bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); }
0386         | OP_MOD 'x' {
0387                 bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
0388         | OP_MOD '%' 'x' {
0389                 bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
0390         ;
0391 
0392 neg
0393         : OP_NEG {
0394                 bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }
0395         ;
0396 
0397 and
0398         : OP_AND '#' number {
0399                 bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); }
0400         | OP_AND 'x' {
0401                 bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
0402         | OP_AND '%' 'x' {
0403                 bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
0404         ;
0405 
0406 or
0407         : OP_OR '#' number {
0408                 bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); }
0409         | OP_OR 'x' {
0410                 bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
0411         | OP_OR '%' 'x' {
0412                 bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
0413         ;
0414 
0415 xor
0416         : OP_XOR '#' number {
0417                 bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); }
0418         | OP_XOR 'x' {
0419                 bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
0420         | OP_XOR '%' 'x' {
0421                 bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
0422         ;
0423 
0424 lsh
0425         : OP_LSH '#' number {
0426                 bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); }
0427         | OP_LSH 'x' {
0428                 bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
0429         | OP_LSH '%' 'x' {
0430                 bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
0431         ;
0432 
0433 rsh
0434         : OP_RSH '#' number {
0435                 bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); }
0436         | OP_RSH 'x' {
0437                 bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
0438         | OP_RSH '%' 'x' {
0439                 bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
0440         ;
0441 
0442 ret
0443         : OP_RET 'a' {
0444                 bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
0445         | OP_RET '%' 'a' {
0446                 bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
0447         | OP_RET 'x' {
0448                 bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
0449         | OP_RET '%' 'x' {
0450                 bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
0451         | OP_RET '#' number {
0452                 bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); }
0453         ;
0454 
0455 tax
0456         : OP_TAX {
0457                 bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }
0458         ;
0459 
0460 txa
0461         : OP_TXA {
0462                 bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); }
0463         ;
0464 
0465 %%
0466 
0467 static int curr_instr = 0;
0468 static struct sock_filter out[BPF_MAXINSNS];
0469 static char **labels, **labels_jt, **labels_jf, **labels_k;
0470 
0471 static void bpf_assert_max(void)
0472 {
0473         if (curr_instr >= BPF_MAXINSNS) {
0474                 fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS);
0475                 exit(1);
0476         }
0477 }
0478 
0479 static void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf,
0480                                uint32_t k)
0481 {
0482         bpf_assert_max();
0483         out[curr_instr].code = code;
0484         out[curr_instr].jt = jt;
0485         out[curr_instr].jf = jf;
0486         out[curr_instr].k = k;
0487         curr_instr++;
0488 }
0489 
0490 static void bpf_set_curr_label(char *label)
0491 {
0492         bpf_assert_max();
0493         labels[curr_instr] = label;
0494 }
0495 
0496 static void bpf_set_jmp_label(char *label, enum jmp_type type)
0497 {
0498         bpf_assert_max();
0499         switch (type) {
0500         case JTL:
0501                 labels_jt[curr_instr] = label;
0502                 break;
0503         case JFL:
0504                 labels_jf[curr_instr] = label;
0505                 break;
0506         case JKL:
0507                 labels_k[curr_instr] = label;
0508                 break;
0509         }
0510 }
0511 
0512 static int bpf_find_insns_offset(const char *label)
0513 {
0514         int i, max = curr_instr, ret = -ENOENT;
0515 
0516         for (i = 0; i < max; i++) {
0517                 if (labels[i] && !strcmp(label, labels[i])) {
0518                         ret = i;
0519                         break;
0520                 }
0521         }
0522 
0523         if (ret == -ENOENT) {
0524                 fprintf(stderr, "no such label \'%s\'!\n", label);
0525                 exit(1);
0526         }
0527 
0528         return ret;
0529 }
0530 
0531 static void bpf_stage_1_insert_insns(void)
0532 {
0533         yyparse();
0534 }
0535 
0536 static void bpf_reduce_k_jumps(void)
0537 {
0538         int i;
0539 
0540         for (i = 0; i < curr_instr; i++) {
0541                 if (labels_k[i]) {
0542                         int off = bpf_find_insns_offset(labels_k[i]);
0543                         out[i].k = (uint32_t) (off - i - 1);
0544                 }
0545         }
0546 }
0547 
0548 static uint8_t bpf_encode_jt_jf_offset(int off, int i)
0549 {
0550         int delta = off - i - 1;
0551 
0552         if (delta < 0 || delta > 255) {
0553                 fprintf(stderr, "error: insn #%d jumps to insn #%d, "
0554                                 "which is out of range\n", i, off);
0555                 exit(1);
0556         }
0557         return (uint8_t) delta;
0558 }
0559 
0560 static void bpf_reduce_jt_jumps(void)
0561 {
0562         int i;
0563 
0564         for (i = 0; i < curr_instr; i++) {
0565                 if (labels_jt[i]) {
0566                         int off = bpf_find_insns_offset(labels_jt[i]);
0567                         out[i].jt = bpf_encode_jt_jf_offset(off, i);
0568                 }
0569         }
0570 }
0571 
0572 static void bpf_reduce_jf_jumps(void)
0573 {
0574         int i;
0575 
0576         for (i = 0; i < curr_instr; i++) {
0577                 if (labels_jf[i]) {
0578                         int off = bpf_find_insns_offset(labels_jf[i]);
0579                         out[i].jf = bpf_encode_jt_jf_offset(off, i);
0580                 }
0581         }
0582 }
0583 
0584 static void bpf_stage_2_reduce_labels(void)
0585 {
0586         bpf_reduce_k_jumps();
0587         bpf_reduce_jt_jumps();
0588         bpf_reduce_jf_jumps();
0589 }
0590 
0591 static void bpf_pretty_print_c(void)
0592 {
0593         int i;
0594 
0595         for (i = 0; i < curr_instr; i++)
0596                 printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code,
0597                        out[i].jt, out[i].jf, out[i].k);
0598 }
0599 
0600 static void bpf_pretty_print(void)
0601 {
0602         int i;
0603 
0604         printf("%u,", curr_instr);
0605         for (i = 0; i < curr_instr; i++)
0606                 printf("%u %u %u %u,", out[i].code,
0607                        out[i].jt, out[i].jf, out[i].k);
0608         printf("\n");
0609 }
0610 
0611 static void bpf_init(void)
0612 {
0613         memset(out, 0, sizeof(out));
0614 
0615         labels = calloc(BPF_MAXINSNS, sizeof(*labels));
0616         assert(labels);
0617         labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt));
0618         assert(labels_jt);
0619         labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf));
0620         assert(labels_jf);
0621         labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k));
0622         assert(labels_k);
0623 }
0624 
0625 static void bpf_destroy_labels(void)
0626 {
0627         int i;
0628 
0629         for (i = 0; i < curr_instr; i++) {
0630                 free(labels_jf[i]);
0631                 free(labels_jt[i]);
0632                 free(labels_k[i]);
0633                 free(labels[i]);
0634         }
0635 }
0636 
0637 static void bpf_destroy(void)
0638 {
0639         bpf_destroy_labels();
0640         free(labels_jt);
0641         free(labels_jf);
0642         free(labels_k);
0643         free(labels);
0644 }
0645 
0646 void bpf_asm_compile(FILE *fp, bool cstyle)
0647 {
0648         yyin = fp;
0649 
0650         bpf_init();
0651         bpf_stage_1_insert_insns();
0652         bpf_stage_2_reduce_labels();
0653         bpf_destroy();
0654 
0655         if (cstyle)
0656                 bpf_pretty_print_c();
0657         else
0658                 bpf_pretty_print();
0659 
0660         if (fp != stdin)
0661                 fclose(yyin);
0662 }
0663 
0664 void yyerror(const char *str)
0665 {
0666         fprintf(stderr, "error: %s at line %d\n", str, yylineno);
0667         exit(1);
0668 }