1 | /* |
---|
2 | * |
---|
3 | * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand. |
---|
4 | * All rights reserved. |
---|
5 | * |
---|
6 | * This file is part of libtrace. |
---|
7 | * |
---|
8 | * This code has been developed by the University of Waikato WAND |
---|
9 | * research group. For further information please see http://www.wand.net.nz/ |
---|
10 | * |
---|
11 | * libtrace is free software; you can redistribute it and/or modify |
---|
12 | * it under the terms of the GNU Lesser General Public License as published by |
---|
13 | * the Free Software Foundation; either version 3 of the License, or |
---|
14 | * (at your option) any later version. |
---|
15 | * |
---|
16 | * libtrace is distributed in the hope that it will be useful, |
---|
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
19 | * GNU Lesser General Public License for more details. |
---|
20 | * |
---|
21 | * You should have received a copy of the GNU Lesser General Public License |
---|
22 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
23 | * |
---|
24 | * |
---|
25 | */ |
---|
26 | |
---|
27 | |
---|
28 | /* |
---|
29 | * This file is not linked into libtrace in the normal way you would expect. |
---|
30 | * |
---|
31 | * It is passed to llvm-gcc, which generates .bc, and then through llc which |
---|
32 | * generates a .cc file of the llvm code to /generate/ this file. This is |
---|
33 | * then included into bpf-jit. |
---|
34 | */ |
---|
35 | #include <inttypes.h> |
---|
36 | #include <arpa/inet.h> |
---|
37 | #define MEMLEN 16 |
---|
38 | |
---|
39 | typedef struct bpf_state_t { |
---|
40 | unsigned int A; |
---|
41 | unsigned int X; |
---|
42 | const unsigned char *P; |
---|
43 | uint32_t len; |
---|
44 | unsigned int mem[MEMLEN]; |
---|
45 | } bpf_state_t; |
---|
46 | |
---|
47 | #define OPCODE(name) \ |
---|
48 | static unsigned int name(bpf_state_t *state, unsigned char jt, unsigned char jf, unsigned long k) |
---|
49 | |
---|
50 | #define P_WORD(x) ntohl(*(uint32_t*)&state->P[x]) |
---|
51 | #define P_HWORD(x) ntohs(*(uint16_t*)&state->P[x]) |
---|
52 | #define P_BYTE(x) (state->P[(x)]) |
---|
53 | |
---|
54 | OPCODE(bpf_ldw_abs) { |
---|
55 | if (k+3>=state->len) |
---|
56 | return 0; /* Read past end of packet: Fail */ |
---|
57 | state->A = P_WORD(k); |
---|
58 | return ~0U; |
---|
59 | } |
---|
60 | OPCODE(bpf_ldh_abs) { |
---|
61 | if (k+1>=state->len) |
---|
62 | return 0; |
---|
63 | state->A = P_HWORD(k); |
---|
64 | return ~0U; |
---|
65 | } |
---|
66 | OPCODE(bpf_ldb_abs) { |
---|
67 | if (k>=state->len) |
---|
68 | return 0; |
---|
69 | state->A = P_BYTE(k); |
---|
70 | return ~0U; |
---|
71 | } |
---|
72 | OPCODE(bpf_ldw_ind) { |
---|
73 | if (k+state->X+3 >= state->len) |
---|
74 | return 0; |
---|
75 | state->A = P_WORD(k+state->X); |
---|
76 | return ~0U; |
---|
77 | } |
---|
78 | OPCODE(bpf_ldh_ind) { |
---|
79 | if (k+state->X+1 >= state->len) |
---|
80 | return 0; |
---|
81 | state->A = P_HWORD(k+state->X); |
---|
82 | return ~0U; |
---|
83 | } |
---|
84 | OPCODE(bpf_ldb_ind) { |
---|
85 | if (k+state->X >= state->len) |
---|
86 | return 0; |
---|
87 | state->A = P_BYTE(k+state->X); |
---|
88 | return ~0U; |
---|
89 | } |
---|
90 | OPCODE(bbf_ldw_ind) { state->A = state->len; return ~0;} |
---|
91 | OPCODE(bpf_ld_imm) { state->A = k; return ~0;} |
---|
92 | OPCODE(bpf_ld_mem) { |
---|
93 | if (k>=MEMLEN) |
---|
94 | return 0; /* Fail Immediately */ |
---|
95 | state->A = state->mem[k]; |
---|
96 | return ~0; |
---|
97 | } |
---|
98 | |
---|
99 | OPCODE(bpf_ldx_imm) { state->X = k; return ~0;} |
---|
100 | OPCODE(bpf_ldx_mem) { |
---|
101 | if (k>=MEMLEN) |
---|
102 | return 0; /* Fail Immediately */ |
---|
103 | state->X = state->mem[k]; |
---|
104 | return ~0; |
---|
105 | } |
---|
106 | OPCODE(bpf_ldx_len) { state->X = state->len; return ~0;} |
---|
107 | OPCODE(bpf_ldx_msh) { |
---|
108 | if (k>=state->len) |
---|
109 | return 0; /* Read past end of packet: Fail */ |
---|
110 | state->X = 4*(P_BYTE(k)&0x0F); |
---|
111 | return ~0; |
---|
112 | } |
---|
113 | |
---|
114 | OPCODE(bpf_sd) { |
---|
115 | if (k>=MEMLEN) |
---|
116 | return 0; /* Fail Immediately */ |
---|
117 | state->mem[k] = state->A; |
---|
118 | return ~0; |
---|
119 | } |
---|
120 | OPCODE(bpf_sdx) { |
---|
121 | if (k>=MEMLEN) |
---|
122 | return 0; /* Fail Immediately */ |
---|
123 | state->mem[k] = state->X; |
---|
124 | return ~0; |
---|
125 | } |
---|
126 | |
---|
127 | OPCODE(bpf_alu_add_k) { state->A += k; return ~0;} |
---|
128 | OPCODE(bpf_alu_sub_k) { state->A -= k; return ~0;} |
---|
129 | OPCODE(bpf_alu_mul_k) { state->A *= k; return ~0;} |
---|
130 | OPCODE(bpf_alu_div_k) { state->A /= k; return ~0;} |
---|
131 | OPCODE(bpf_alu_and_k) { state->A &= k; return ~0;} |
---|
132 | OPCODE(bpf_alu_or_k) { state->A |= k; return ~0;} |
---|
133 | OPCODE(bpf_alu_lsh_k) { state->A = state->A << k; return ~0;} |
---|
134 | OPCODE(bpf_alu_rsh_k) { state->A = state->A >> k; return ~0;} |
---|
135 | OPCODE(bpf_alu_neg) { state->A = -state->A; return ~0;} |
---|
136 | |
---|
137 | OPCODE(bpf_alu_add_x) { state->A += state->X; return ~0;} |
---|
138 | OPCODE(bpf_alu_sub_x) { state->A -= state->X; return ~0;} |
---|
139 | OPCODE(bpf_alu_mul_x) { state->A *= state->X; return ~0;} |
---|
140 | OPCODE(bpf_alu_div_x) { state->A /= state->X; return ~0;} |
---|
141 | OPCODE(bpf_alu_and_x) { state->A &= state->X; return ~0;} |
---|
142 | OPCODE(bpf_alu_or_x) { state->A |= state->X; return ~0;} |
---|
143 | OPCODE(bpf_alu_lsh_x) { state->A = state->A << state->X; return ~0;} |
---|
144 | OPCODE(bpf_alu_rsh_x) { state->A = state->A >> state->X; return ~0;} |
---|
145 | |
---|
146 | /* These are created by code |
---|
147 | OPCODE(bpf_ja) { state->pc += k; return ~0;} |
---|
148 | OPCODE(bpf_gt_k) { state->pc += (state->A > k) ? jt : jf; return ~0;} |
---|
149 | OPCODE(bpf_ge_k) { state->pc += (state->A >= k) ? jt : jf; return ~0;} |
---|
150 | OPCODE(bpf_eq_k) { state->pc += (state->A == k) ? jt : jf; return ~0;} |
---|
151 | OPCODE(bpf_set_k) { state->pc += (state->A & k) ? jt : jf; return ~0;} |
---|
152 | OPCODE(bpf_gt_x) { state->pc += (state->A > state->X) ? jt : jf; return ~0;} |
---|
153 | OPCODE(bpf_ge_x) { state->pc += (state->A >= state->X) ? jt : jf; return ~0;} |
---|
154 | OPCODE(bpf_eq_x) { state->pc += (state->A == state->X) ? jt : jf; return ~0;} |
---|
155 | OPCODE(bpf_set_x) { state->pc += (state->A & state->X) ? jt : jf; return ~0;} |
---|
156 | */ |
---|
157 | |
---|
158 | OPCODE(bpf_ret_a) { return state->A; } |
---|
159 | OPCODE(bpf_ret_k) { return k; } |
---|
160 | |
---|
161 | OPCODE(bpf_tax) { state->X = state->A; return ~0; } |
---|
162 | OPCODE(bpf_txa) { state->A = state->X; return ~0; } |
---|
163 | |
---|