mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-08 01:08:03 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
34
tools/net/Makefile
Normal file
34
tools/net/Makefile
Normal file
|
@ -0,0 +1,34 @@
|
|||
prefix = /usr
|
||||
|
||||
CC = gcc
|
||||
LEX = flex
|
||||
YACC = bison
|
||||
|
||||
%.yacc.c: %.y
|
||||
$(YACC) -o $@ -d $<
|
||||
|
||||
%.lex.c: %.l
|
||||
$(LEX) -o $@ $<
|
||||
|
||||
all : bpf_jit_disasm bpf_dbg bpf_asm
|
||||
|
||||
bpf_jit_disasm : CFLAGS = -Wall -O2 -DPACKAGE='bpf_jit_disasm'
|
||||
bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
|
||||
bpf_jit_disasm : bpf_jit_disasm.o
|
||||
|
||||
bpf_dbg : CFLAGS = -Wall -O2
|
||||
bpf_dbg : LDLIBS = -lreadline
|
||||
bpf_dbg : bpf_dbg.o
|
||||
|
||||
bpf_asm : CFLAGS = -Wall -O2 -I.
|
||||
bpf_asm : LDLIBS =
|
||||
bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o
|
||||
bpf_exp.lex.o : bpf_exp.yacc.c
|
||||
|
||||
clean :
|
||||
rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.*
|
||||
|
||||
install :
|
||||
install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm
|
||||
install bpf_dbg $(prefix)/bin/bpf_dbg
|
||||
install bpf_asm $(prefix)/bin/bpf_asm
|
52
tools/net/bpf_asm.c
Normal file
52
tools/net/bpf_asm.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Minimal BPF assembler
|
||||
*
|
||||
* Instead of libpcap high-level filter expressions, it can be quite
|
||||
* useful to define filters in low-level BPF assembler (that is kept
|
||||
* close to Steven McCanne and Van Jacobson's original BPF paper).
|
||||
* In particular for BPF JIT implementors, JIT security auditors, or
|
||||
* just for defining BPF expressions that contain extensions which are
|
||||
* not supported by compilers.
|
||||
*
|
||||
* How to get into it:
|
||||
*
|
||||
* 1) read Documentation/networking/filter.txt
|
||||
* 2) Run `bpf_asm [-c] <filter-prog file>` to translate into binary
|
||||
* blob that is loadable with xt_bpf, cls_bpf et al. Note: -c will
|
||||
* pretty print a C-like construct.
|
||||
*
|
||||
* Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
extern void bpf_asm_compile(FILE *fp, bool cstyle);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp = stdin;
|
||||
bool cstyle = false;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strncmp("-c", argv[i], 2)) {
|
||||
cstyle = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
fp = fopen(argv[i], "r");
|
||||
if (!fp) {
|
||||
fp = stdin;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
bpf_asm_compile(fp, cstyle);
|
||||
|
||||
return 0;
|
||||
}
|
1395
tools/net/bpf_dbg.c
Normal file
1395
tools/net/bpf_dbg.c
Normal file
File diff suppressed because it is too large
Load diff
144
tools/net/bpf_exp.l
Normal file
144
tools/net/bpf_exp.l
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* BPF asm code lexer
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Syntax kept close to:
|
||||
*
|
||||
* Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new
|
||||
* architecture for user-level packet capture. In Proceedings of the
|
||||
* USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993
|
||||
* Conference Proceedings (USENIX'93). USENIX Association, Berkeley,
|
||||
* CA, USA, 2-2.
|
||||
*
|
||||
* Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bpf_exp.yacc.h"
|
||||
|
||||
extern void yyerror(const char *str);
|
||||
|
||||
%}
|
||||
|
||||
%option align
|
||||
%option ecs
|
||||
|
||||
%option nounput
|
||||
%option noreject
|
||||
%option noinput
|
||||
%option noyywrap
|
||||
|
||||
%option 8bit
|
||||
%option caseless
|
||||
%option yylineno
|
||||
|
||||
%%
|
||||
|
||||
"ldb" { return OP_LDB; }
|
||||
"ldh" { return OP_LDH; }
|
||||
"ld" { return OP_LD; }
|
||||
"ldi" { return OP_LDI; }
|
||||
"ldx" { return OP_LDX; }
|
||||
"ldxi" { return OP_LDXI; }
|
||||
"ldxb" { return OP_LDXB; }
|
||||
"st" { return OP_ST; }
|
||||
"stx" { return OP_STX; }
|
||||
"jmp" { return OP_JMP; }
|
||||
"ja" { return OP_JMP; }
|
||||
"jeq" { return OP_JEQ; }
|
||||
"jneq" { return OP_JNEQ; }
|
||||
"jne" { return OP_JNEQ; }
|
||||
"jlt" { return OP_JLT; }
|
||||
"jle" { return OP_JLE; }
|
||||
"jgt" { return OP_JGT; }
|
||||
"jge" { return OP_JGE; }
|
||||
"jset" { return OP_JSET; }
|
||||
"add" { return OP_ADD; }
|
||||
"sub" { return OP_SUB; }
|
||||
"mul" { return OP_MUL; }
|
||||
"div" { return OP_DIV; }
|
||||
"mod" { return OP_MOD; }
|
||||
"neg" { return OP_NEG; }
|
||||
"and" { return OP_AND; }
|
||||
"xor" { return OP_XOR; }
|
||||
"or" { return OP_OR; }
|
||||
"lsh" { return OP_LSH; }
|
||||
"rsh" { return OP_RSH; }
|
||||
"ret" { return OP_RET; }
|
||||
"tax" { return OP_TAX; }
|
||||
"txa" { return OP_TXA; }
|
||||
|
||||
"#"?("len") { return K_PKT_LEN; }
|
||||
"#"?("proto") { return K_PROTO; }
|
||||
"#"?("type") { return K_TYPE; }
|
||||
"#"?("poff") { return K_POFF; }
|
||||
"#"?("ifidx") { return K_IFIDX; }
|
||||
"#"?("nla") { return K_NLATTR; }
|
||||
"#"?("nlan") { return K_NLATTR_NEST; }
|
||||
"#"?("mark") { return K_MARK; }
|
||||
"#"?("queue") { return K_QUEUE; }
|
||||
"#"?("hatype") { return K_HATYPE; }
|
||||
"#"?("rxhash") { return K_RXHASH; }
|
||||
"#"?("cpu") { return K_CPU; }
|
||||
"#"?("vlan_tci") { return K_VLANT; }
|
||||
"#"?("vlan_pr") { return K_VLANP; }
|
||||
"#"?("rand") { return K_RAND; }
|
||||
|
||||
":" { return ':'; }
|
||||
"," { return ','; }
|
||||
"#" { return '#'; }
|
||||
"%" { return '%'; }
|
||||
"[" { return '['; }
|
||||
"]" { return ']'; }
|
||||
"(" { return '('; }
|
||||
")" { return ')'; }
|
||||
"x" { return 'x'; }
|
||||
"a" { return 'a'; }
|
||||
"+" { return '+'; }
|
||||
"M" { return 'M'; }
|
||||
"*" { return '*'; }
|
||||
"&" { return '&'; }
|
||||
|
||||
([0][x][a-fA-F0-9]+) {
|
||||
yylval.number = strtoul(yytext, NULL, 16);
|
||||
return number;
|
||||
}
|
||||
([0][b][0-1]+) {
|
||||
yylval.number = strtol(yytext + 2, NULL, 2);
|
||||
return number;
|
||||
}
|
||||
(([0])|([-+]?[1-9][0-9]*)) {
|
||||
yylval.number = strtol(yytext, NULL, 10);
|
||||
return number;
|
||||
}
|
||||
([0][0-9]+) {
|
||||
yylval.number = strtol(yytext + 1, NULL, 8);
|
||||
return number;
|
||||
}
|
||||
[a-zA-Z_][a-zA-Z0-9_]+ {
|
||||
yylval.label = strdup(yytext);
|
||||
return label;
|
||||
}
|
||||
|
||||
"/*"([^\*]|\*[^/])*"*/" { /* NOP */ }
|
||||
";"[^\n]* { /* NOP */ }
|
||||
^#.* { /* NOP */ }
|
||||
[ \t]+ { /* NOP */ }
|
||||
[ \n]+ { /* NOP */ }
|
||||
|
||||
. {
|
||||
printf("unknown character \'%s\'", yytext);
|
||||
yyerror("lex unknown character");
|
||||
}
|
||||
|
||||
%%
|
771
tools/net/bpf_exp.y
Normal file
771
tools/net/bpf_exp.y
Normal file
|
@ -0,0 +1,771 @@
|
|||
/*
|
||||
* BPF asm code parser
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* Syntax kept close to:
|
||||
*
|
||||
* Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new
|
||||
* architecture for user-level packet capture. In Proceedings of the
|
||||
* USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993
|
||||
* Conference Proceedings (USENIX'93). USENIX Association, Berkeley,
|
||||
* CA, USA, 2-2.
|
||||
*
|
||||
* Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <linux/filter.h>
|
||||
|
||||
#include "bpf_exp.yacc.h"
|
||||
|
||||
enum jmp_type { JTL, JFL, JKL };
|
||||
|
||||
extern FILE *yyin;
|
||||
extern int yylex(void);
|
||||
extern void yyerror(const char *str);
|
||||
|
||||
extern void bpf_asm_compile(FILE *fp, bool cstyle);
|
||||
static void bpf_set_curr_instr(uint16_t op, uint8_t jt, uint8_t jf, uint32_t k);
|
||||
static void bpf_set_curr_label(char *label);
|
||||
static void bpf_set_jmp_label(char *label, enum jmp_type type);
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
char *label;
|
||||
uint32_t number;
|
||||
}
|
||||
|
||||
%token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE
|
||||
%token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH
|
||||
%token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI
|
||||
%token OP_LDXI
|
||||
|
||||
%token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE
|
||||
%token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_POFF K_RAND
|
||||
|
||||
%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
|
||||
|
||||
%token number label
|
||||
|
||||
%type <label> label
|
||||
%type <number> number
|
||||
|
||||
%%
|
||||
|
||||
prog
|
||||
: line
|
||||
| prog line
|
||||
;
|
||||
|
||||
line
|
||||
: instr
|
||||
| labelled_instr
|
||||
;
|
||||
|
||||
labelled_instr
|
||||
: labelled instr
|
||||
;
|
||||
|
||||
instr
|
||||
: ldb
|
||||
| ldh
|
||||
| ld
|
||||
| ldi
|
||||
| ldx
|
||||
| ldxi
|
||||
| st
|
||||
| stx
|
||||
| jmp
|
||||
| jeq
|
||||
| jneq
|
||||
| jlt
|
||||
| jle
|
||||
| jgt
|
||||
| jge
|
||||
| jset
|
||||
| add
|
||||
| sub
|
||||
| mul
|
||||
| div
|
||||
| mod
|
||||
| neg
|
||||
| and
|
||||
| or
|
||||
| xor
|
||||
| lsh
|
||||
| rsh
|
||||
| ret
|
||||
| tax
|
||||
| txa
|
||||
;
|
||||
|
||||
labelled
|
||||
: label ':' { bpf_set_curr_label($1); }
|
||||
;
|
||||
|
||||
ldb
|
||||
: OP_LDB '[' 'x' '+' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $5); }
|
||||
| OP_LDB '[' '%' 'x' '+' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $6); }
|
||||
| OP_LDB '[' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, $3); }
|
||||
| OP_LDB K_PROTO {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PROTOCOL); }
|
||||
| OP_LDB K_TYPE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PKTTYPE); }
|
||||
| OP_LDB K_IFIDX {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_IFINDEX); }
|
||||
| OP_LDB K_NLATTR {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_NLATTR); }
|
||||
| OP_LDB K_NLATTR_NEST {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
|
||||
| OP_LDB K_MARK {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_MARK); }
|
||||
| OP_LDB K_QUEUE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_QUEUE); }
|
||||
| OP_LDB K_HATYPE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_HATYPE); }
|
||||
| OP_LDB K_RXHASH {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_RXHASH); }
|
||||
| OP_LDB K_CPU {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_CPU); }
|
||||
| OP_LDB K_VLANT {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_VLAN_TAG); }
|
||||
| OP_LDB K_VLANP {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
|
||||
| OP_LDB K_POFF {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
|
||||
| OP_LDB K_RAND {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_RANDOM); }
|
||||
;
|
||||
|
||||
ldh
|
||||
: OP_LDH '[' 'x' '+' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); }
|
||||
| OP_LDH '[' '%' 'x' '+' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); }
|
||||
| OP_LDH '[' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); }
|
||||
| OP_LDH K_PROTO {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PROTOCOL); }
|
||||
| OP_LDH K_TYPE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PKTTYPE); }
|
||||
| OP_LDH K_IFIDX {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_IFINDEX); }
|
||||
| OP_LDH K_NLATTR {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_NLATTR); }
|
||||
| OP_LDH K_NLATTR_NEST {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
|
||||
| OP_LDH K_MARK {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_MARK); }
|
||||
| OP_LDH K_QUEUE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_QUEUE); }
|
||||
| OP_LDH K_HATYPE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_HATYPE); }
|
||||
| OP_LDH K_RXHASH {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_RXHASH); }
|
||||
| OP_LDH K_CPU {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_CPU); }
|
||||
| OP_LDH K_VLANT {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_VLAN_TAG); }
|
||||
| OP_LDH K_VLANP {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
|
||||
| OP_LDH K_POFF {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
|
||||
| OP_LDH K_RAND {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_RANDOM); }
|
||||
;
|
||||
|
||||
ldi
|
||||
: OP_LDI '#' number {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
|
||||
| OP_LDI number {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); }
|
||||
;
|
||||
|
||||
ld
|
||||
: OP_LD '#' number {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); }
|
||||
| OP_LD K_PKT_LEN {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); }
|
||||
| OP_LD K_PROTO {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PROTOCOL); }
|
||||
| OP_LD K_TYPE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PKTTYPE); }
|
||||
| OP_LD K_IFIDX {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_IFINDEX); }
|
||||
| OP_LD K_NLATTR {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_NLATTR); }
|
||||
| OP_LD K_NLATTR_NEST {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_NLATTR_NEST); }
|
||||
| OP_LD K_MARK {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_MARK); }
|
||||
| OP_LD K_QUEUE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_QUEUE); }
|
||||
| OP_LD K_HATYPE {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_HATYPE); }
|
||||
| OP_LD K_RXHASH {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_RXHASH); }
|
||||
| OP_LD K_CPU {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_CPU); }
|
||||
| OP_LD K_VLANT {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_VLAN_TAG); }
|
||||
| OP_LD K_VLANP {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
|
||||
| OP_LD K_POFF {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_PAY_OFFSET); }
|
||||
| OP_LD K_RAND {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
|
||||
SKF_AD_OFF + SKF_AD_RANDOM); }
|
||||
| OP_LD 'M' '[' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
|
||||
| OP_LD '[' 'x' '+' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); }
|
||||
| OP_LD '[' '%' 'x' '+' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); }
|
||||
| OP_LD '[' number ']' {
|
||||
bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); }
|
||||
;
|
||||
|
||||
ldxi
|
||||
: OP_LDXI '#' number {
|
||||
bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
|
||||
| OP_LDXI number {
|
||||
bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); }
|
||||
;
|
||||
|
||||
ldx
|
||||
: OP_LDX '#' number {
|
||||
bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); }
|
||||
| OP_LDX K_PKT_LEN {
|
||||
bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); }
|
||||
| OP_LDX 'M' '[' number ']' {
|
||||
bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); }
|
||||
| OP_LDXB number '*' '(' '[' number ']' '&' number ')' {
|
||||
if ($2 != 4 || $9 != 0xf) {
|
||||
fprintf(stderr, "ldxb offset not supported!\n");
|
||||
exit(0);
|
||||
} else {
|
||||
bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
|
||||
| OP_LDX number '*' '(' '[' number ']' '&' number ')' {
|
||||
if ($2 != 4 || $9 != 0xf) {
|
||||
fprintf(stderr, "ldxb offset not supported!\n");
|
||||
exit(0);
|
||||
} else {
|
||||
bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } }
|
||||
;
|
||||
|
||||
st
|
||||
: OP_ST 'M' '[' number ']' {
|
||||
bpf_set_curr_instr(BPF_ST, 0, 0, $4); }
|
||||
;
|
||||
|
||||
stx
|
||||
: OP_STX 'M' '[' number ']' {
|
||||
bpf_set_curr_instr(BPF_STX, 0, 0, $4); }
|
||||
;
|
||||
|
||||
jmp
|
||||
: OP_JMP label {
|
||||
bpf_set_jmp_label($2, JKL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); }
|
||||
;
|
||||
|
||||
jeq
|
||||
: OP_JEQ '#' number ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
|
||||
| OP_JEQ 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_jmp_label($6, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
|
||||
| OP_JEQ '%' 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
|
||||
| OP_JEQ '#' number ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
|
||||
| OP_JEQ 'x' ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
|
||||
| OP_JEQ '%' 'x' ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
jneq
|
||||
: OP_JNEQ '#' number ',' label {
|
||||
bpf_set_jmp_label($5, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); }
|
||||
| OP_JNEQ 'x' ',' label {
|
||||
bpf_set_jmp_label($4, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
|
||||
| OP_JNEQ '%' 'x' ',' label {
|
||||
bpf_set_jmp_label($5, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
jlt
|
||||
: OP_JLT '#' number ',' label {
|
||||
bpf_set_jmp_label($5, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
|
||||
| OP_JLT 'x' ',' label {
|
||||
bpf_set_jmp_label($4, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
|
||||
| OP_JLT '%' 'x' ',' label {
|
||||
bpf_set_jmp_label($5, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
jle
|
||||
: OP_JLE '#' number ',' label {
|
||||
bpf_set_jmp_label($5, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
|
||||
| OP_JLE 'x' ',' label {
|
||||
bpf_set_jmp_label($4, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
|
||||
| OP_JLE '%' 'x' ',' label {
|
||||
bpf_set_jmp_label($5, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
jgt
|
||||
: OP_JGT '#' number ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
|
||||
| OP_JGT 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_jmp_label($6, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
|
||||
| OP_JGT '%' 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
|
||||
| OP_JGT '#' number ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); }
|
||||
| OP_JGT 'x' ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
|
||||
| OP_JGT '%' 'x' ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
jge
|
||||
: OP_JGE '#' number ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
|
||||
| OP_JGE 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_jmp_label($6, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
|
||||
| OP_JGE '%' 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
|
||||
| OP_JGE '#' number ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); }
|
||||
| OP_JGE 'x' ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
|
||||
| OP_JGE '%' 'x' ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
jset
|
||||
: OP_JSET '#' number ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
|
||||
| OP_JSET 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_jmp_label($6, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
|
||||
| OP_JSET '%' 'x' ',' label ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_jmp_label($7, JFL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
|
||||
| OP_JSET '#' number ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); }
|
||||
| OP_JSET 'x' ',' label {
|
||||
bpf_set_jmp_label($4, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
|
||||
| OP_JSET '%' 'x' ',' label {
|
||||
bpf_set_jmp_label($5, JTL);
|
||||
bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
add
|
||||
: OP_ADD '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); }
|
||||
| OP_ADD 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
|
||||
| OP_ADD '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
sub
|
||||
: OP_SUB '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); }
|
||||
| OP_SUB 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
|
||||
| OP_SUB '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
mul
|
||||
: OP_MUL '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); }
|
||||
| OP_MUL 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
|
||||
| OP_MUL '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
div
|
||||
: OP_DIV '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); }
|
||||
| OP_DIV 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
|
||||
| OP_DIV '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
mod
|
||||
: OP_MOD '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); }
|
||||
| OP_MOD 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
|
||||
| OP_MOD '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
neg
|
||||
: OP_NEG {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); }
|
||||
;
|
||||
|
||||
and
|
||||
: OP_AND '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); }
|
||||
| OP_AND 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
|
||||
| OP_AND '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
or
|
||||
: OP_OR '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); }
|
||||
| OP_OR 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
|
||||
| OP_OR '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
xor
|
||||
: OP_XOR '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); }
|
||||
| OP_XOR 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
|
||||
| OP_XOR '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
lsh
|
||||
: OP_LSH '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); }
|
||||
| OP_LSH 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
|
||||
| OP_LSH '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
rsh
|
||||
: OP_RSH '#' number {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); }
|
||||
| OP_RSH 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
|
||||
| OP_RSH '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); }
|
||||
;
|
||||
|
||||
ret
|
||||
: OP_RET 'a' {
|
||||
bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
|
||||
| OP_RET '%' 'a' {
|
||||
bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); }
|
||||
| OP_RET 'x' {
|
||||
bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
|
||||
| OP_RET '%' 'x' {
|
||||
bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); }
|
||||
| OP_RET '#' number {
|
||||
bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); }
|
||||
;
|
||||
|
||||
tax
|
||||
: OP_TAX {
|
||||
bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); }
|
||||
;
|
||||
|
||||
txa
|
||||
: OP_TXA {
|
||||
bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
static int curr_instr = 0;
|
||||
static struct sock_filter out[BPF_MAXINSNS];
|
||||
static char **labels, **labels_jt, **labels_jf, **labels_k;
|
||||
|
||||
static void bpf_assert_max(void)
|
||||
{
|
||||
if (curr_instr >= BPF_MAXINSNS) {
|
||||
fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf,
|
||||
uint32_t k)
|
||||
{
|
||||
bpf_assert_max();
|
||||
out[curr_instr].code = code;
|
||||
out[curr_instr].jt = jt;
|
||||
out[curr_instr].jf = jf;
|
||||
out[curr_instr].k = k;
|
||||
curr_instr++;
|
||||
}
|
||||
|
||||
static void bpf_set_curr_label(char *label)
|
||||
{
|
||||
bpf_assert_max();
|
||||
labels[curr_instr] = label;
|
||||
}
|
||||
|
||||
static void bpf_set_jmp_label(char *label, enum jmp_type type)
|
||||
{
|
||||
bpf_assert_max();
|
||||
switch (type) {
|
||||
case JTL:
|
||||
labels_jt[curr_instr] = label;
|
||||
break;
|
||||
case JFL:
|
||||
labels_jf[curr_instr] = label;
|
||||
break;
|
||||
case JKL:
|
||||
labels_k[curr_instr] = label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int bpf_find_insns_offset(const char *label)
|
||||
{
|
||||
int i, max = curr_instr, ret = -ENOENT;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (labels[i] && !strcmp(label, labels[i])) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == -ENOENT) {
|
||||
fprintf(stderr, "no such label \'%s\'!\n", label);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bpf_stage_1_insert_insns(void)
|
||||
{
|
||||
yyparse();
|
||||
}
|
||||
|
||||
static void bpf_reduce_k_jumps(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < curr_instr; i++) {
|
||||
if (labels_k[i]) {
|
||||
int off = bpf_find_insns_offset(labels_k[i]);
|
||||
out[i].k = (uint32_t) (off - i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bpf_reduce_jt_jumps(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < curr_instr; i++) {
|
||||
if (labels_jt[i]) {
|
||||
int off = bpf_find_insns_offset(labels_jt[i]);
|
||||
out[i].jt = (uint8_t) (off - i -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bpf_reduce_jf_jumps(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < curr_instr; i++) {
|
||||
if (labels_jf[i]) {
|
||||
int off = bpf_find_insns_offset(labels_jf[i]);
|
||||
out[i].jf = (uint8_t) (off - i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bpf_stage_2_reduce_labels(void)
|
||||
{
|
||||
bpf_reduce_k_jumps();
|
||||
bpf_reduce_jt_jumps();
|
||||
bpf_reduce_jf_jumps();
|
||||
}
|
||||
|
||||
static void bpf_pretty_print_c(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < curr_instr; i++)
|
||||
printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code,
|
||||
out[i].jt, out[i].jf, out[i].k);
|
||||
}
|
||||
|
||||
static void bpf_pretty_print(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("%u,", curr_instr);
|
||||
for (i = 0; i < curr_instr; i++)
|
||||
printf("%u %u %u %u,", out[i].code,
|
||||
out[i].jt, out[i].jf, out[i].k);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void bpf_init(void)
|
||||
{
|
||||
memset(out, 0, sizeof(out));
|
||||
|
||||
labels = calloc(BPF_MAXINSNS, sizeof(*labels));
|
||||
assert(labels);
|
||||
labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt));
|
||||
assert(labels_jt);
|
||||
labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf));
|
||||
assert(labels_jf);
|
||||
labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k));
|
||||
assert(labels_k);
|
||||
}
|
||||
|
||||
static void bpf_destroy_labels(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < curr_instr; i++) {
|
||||
free(labels_jf[i]);
|
||||
free(labels_jt[i]);
|
||||
free(labels_k[i]);
|
||||
free(labels[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void bpf_destroy(void)
|
||||
{
|
||||
bpf_destroy_labels();
|
||||
free(labels_jt);
|
||||
free(labels_jf);
|
||||
free(labels_k);
|
||||
free(labels);
|
||||
}
|
||||
|
||||
void bpf_asm_compile(FILE *fp, bool cstyle)
|
||||
{
|
||||
yyin = fp;
|
||||
|
||||
bpf_init();
|
||||
bpf_stage_1_insert_insns();
|
||||
bpf_stage_2_reduce_labels();
|
||||
bpf_destroy();
|
||||
|
||||
if (cstyle)
|
||||
bpf_pretty_print_c();
|
||||
else
|
||||
bpf_pretty_print();
|
||||
|
||||
if (fp != stdin)
|
||||
fclose(yyin);
|
||||
}
|
||||
|
||||
void yyerror(const char *str)
|
||||
{
|
||||
exit(1);
|
||||
}
|
197
tools/net/bpf_jit_disasm.c
Normal file
197
tools/net/bpf_jit_disasm.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Minimal BPF JIT image disassembler
|
||||
*
|
||||
* Disassembles BPF JIT compiler emitted opcodes back to asm insn's for
|
||||
* debugging or verification purposes.
|
||||
*
|
||||
* To get the disassembly of the JIT code, do the following:
|
||||
*
|
||||
* 1) `echo 2 > /proc/sys/net/core/bpf_jit_enable`
|
||||
* 2) Load a BPF filter (e.g. `tcpdump -p -n -s 0 -i eth1 host 192.168.20.0/24`)
|
||||
* 3) Run e.g. `bpf_jit_disasm -o` to read out the last JIT code
|
||||
*
|
||||
* Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <bfd.h>
|
||||
#include <dis-asm.h>
|
||||
#include <sys/klog.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
static void get_exec_path(char *tpath, size_t size)
|
||||
{
|
||||
char *path;
|
||||
ssize_t len;
|
||||
|
||||
snprintf(tpath, size, "/proc/%d/exe", (int) getpid());
|
||||
tpath[size - 1] = 0;
|
||||
|
||||
path = strdup(tpath);
|
||||
assert(path);
|
||||
|
||||
len = readlink(path, tpath, size);
|
||||
tpath[len] = 0;
|
||||
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void get_asm_insns(uint8_t *image, size_t len, int opcodes)
|
||||
{
|
||||
int count, i, pc = 0;
|
||||
char tpath[256];
|
||||
struct disassemble_info info;
|
||||
disassembler_ftype disassemble;
|
||||
bfd *bfdf;
|
||||
|
||||
memset(tpath, 0, sizeof(tpath));
|
||||
get_exec_path(tpath, sizeof(tpath));
|
||||
|
||||
bfdf = bfd_openr(tpath, NULL);
|
||||
assert(bfdf);
|
||||
assert(bfd_check_format(bfdf, bfd_object));
|
||||
|
||||
init_disassemble_info(&info, stdout, (fprintf_ftype) fprintf);
|
||||
info.arch = bfd_get_arch(bfdf);
|
||||
info.mach = bfd_get_mach(bfdf);
|
||||
info.buffer = image;
|
||||
info.buffer_length = len;
|
||||
|
||||
disassemble_init_for_target(&info);
|
||||
|
||||
disassemble = disassembler(bfdf);
|
||||
assert(disassemble);
|
||||
|
||||
do {
|
||||
printf("%4x:\t", pc);
|
||||
|
||||
count = disassemble(pc, &info);
|
||||
|
||||
if (opcodes) {
|
||||
printf("\n\t");
|
||||
for (i = 0; i < count; ++i)
|
||||
printf("%02x ", (uint8_t) image[pc + i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
pc += count;
|
||||
} while(count > 0 && pc < len);
|
||||
|
||||
bfd_close(bfdf);
|
||||
}
|
||||
|
||||
static char *get_klog_buff(int *klen)
|
||||
{
|
||||
int ret, len = klogctl(10, NULL, 0);
|
||||
char *buff = malloc(len);
|
||||
|
||||
assert(buff && klen);
|
||||
ret = klogctl(3, buff, len);
|
||||
assert(ret >= 0);
|
||||
*klen = ret;
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
static void put_klog_buff(char *buff)
|
||||
{
|
||||
free(buff);
|
||||
}
|
||||
|
||||
static int get_last_jit_image(char *haystack, size_t hlen,
|
||||
uint8_t *image, size_t ilen)
|
||||
{
|
||||
char *ptr, *pptr, *tmp;
|
||||
off_t off = 0;
|
||||
int ret, flen, proglen, pass, ulen = 0;
|
||||
regmatch_t pmatch[1];
|
||||
unsigned long base;
|
||||
regex_t regex;
|
||||
|
||||
if (hlen == 0)
|
||||
return 0;
|
||||
|
||||
ret = regcomp(®ex, "flen=[[:alnum:]]+ proglen=[[:digit:]]+ "
|
||||
"pass=[[:digit:]]+ image=[[:xdigit:]]+", REG_EXTENDED);
|
||||
assert(ret == 0);
|
||||
|
||||
ptr = haystack;
|
||||
while (1) {
|
||||
ret = regexec(®ex, ptr, 1, pmatch, 0);
|
||||
if (ret == 0) {
|
||||
ptr += pmatch[0].rm_eo;
|
||||
off += pmatch[0].rm_eo;
|
||||
assert(off < hlen);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = haystack + off - (pmatch[0].rm_eo - pmatch[0].rm_so);
|
||||
ret = sscanf(ptr, "flen=%d proglen=%d pass=%d image=%lx",
|
||||
&flen, &proglen, &pass, &base);
|
||||
if (ret != 4)
|
||||
return 0;
|
||||
|
||||
tmp = ptr = haystack + off;
|
||||
while ((ptr = strtok(tmp, "\n")) != NULL && ulen < ilen) {
|
||||
tmp = NULL;
|
||||
if (!strstr(ptr, "JIT code"))
|
||||
continue;
|
||||
pptr = ptr;
|
||||
while ((ptr = strstr(pptr, ":")))
|
||||
pptr = ptr + 1;
|
||||
ptr = pptr;
|
||||
do {
|
||||
image[ulen++] = (uint8_t) strtoul(pptr, &pptr, 16);
|
||||
if (ptr == pptr || ulen >= ilen) {
|
||||
ulen--;
|
||||
break;
|
||||
}
|
||||
ptr = pptr;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
assert(ulen == proglen);
|
||||
printf("%d bytes emitted from JIT compiler (pass:%d, flen:%d)\n",
|
||||
proglen, pass, flen);
|
||||
printf("%lx + <x>:\n", base);
|
||||
|
||||
regfree(®ex);
|
||||
return ulen;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int len, klen, opcodes = 0;
|
||||
char *kbuff;
|
||||
static uint8_t image[32768];
|
||||
|
||||
if (argc > 1) {
|
||||
if (!strncmp("-o", argv[argc - 1], 2)) {
|
||||
opcodes = 1;
|
||||
} else {
|
||||
printf("usage: bpf_jit_disasm [-o: show opcodes]\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
bfd_init();
|
||||
memset(image, 0, sizeof(image));
|
||||
|
||||
kbuff = get_klog_buff(&klen);
|
||||
|
||||
len = get_last_jit_image(kbuff, klen, image, sizeof(image));
|
||||
if (len > 0)
|
||||
get_asm_insns(image, len, opcodes);
|
||||
|
||||
put_klog_buff(kbuff);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue