1*7304104dSAndroid Build Coastguard Worker /* Disassembler for BPF.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2016, 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of either
7*7304104dSAndroid Build Coastguard Worker
8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker your option) any later version
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker or
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker your option) any later version
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23*7304104dSAndroid Build Coastguard Worker General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker
25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
28*7304104dSAndroid Build Coastguard Worker
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include <assert.h>
34*7304104dSAndroid Build Coastguard Worker #include <string.h>
35*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
36*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
37*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
38*7304104dSAndroid Build Coastguard Worker #include "bpf.h"
39*7304104dSAndroid Build Coastguard Worker
40*7304104dSAndroid Build Coastguard Worker #include "common.h"
41*7304104dSAndroid Build Coastguard Worker #include "libeblP.h"
42*7304104dSAndroid Build Coastguard Worker
43*7304104dSAndroid Build Coastguard Worker static const char class_string[8][8] = {
44*7304104dSAndroid Build Coastguard Worker [BPF_LD] = "ld",
45*7304104dSAndroid Build Coastguard Worker [BPF_LDX] = "ldx",
46*7304104dSAndroid Build Coastguard Worker [BPF_ST] = "st",
47*7304104dSAndroid Build Coastguard Worker [BPF_STX] = "stx",
48*7304104dSAndroid Build Coastguard Worker [BPF_ALU] = "alu",
49*7304104dSAndroid Build Coastguard Worker [BPF_JMP] = "jmp",
50*7304104dSAndroid Build Coastguard Worker [BPF_RET] = "6", /* completely unused in ebpf */
51*7304104dSAndroid Build Coastguard Worker [BPF_ALU64] = "alu64",
52*7304104dSAndroid Build Coastguard Worker };
53*7304104dSAndroid Build Coastguard Worker
54*7304104dSAndroid Build Coastguard Worker
55*7304104dSAndroid Build Coastguard Worker #define REG(N) "r%" #N "$d"
56*7304104dSAndroid Build Coastguard Worker #define REGU(N) "(u32)" REG(N)
57*7304104dSAndroid Build Coastguard Worker #define REGS(N) "(s64)" REG(N)
58*7304104dSAndroid Build Coastguard Worker
59*7304104dSAndroid Build Coastguard Worker #define IMMS(N) "%" #N "$d"
60*7304104dSAndroid Build Coastguard Worker #define IMMX(N) "%" #N "$#x"
61*7304104dSAndroid Build Coastguard Worker
62*7304104dSAndroid Build Coastguard Worker #define OFF(N) "%" #N "$+d"
63*7304104dSAndroid Build Coastguard Worker #define JMP(N) "%" #N "$#x"
64*7304104dSAndroid Build Coastguard Worker
65*7304104dSAndroid Build Coastguard Worker #define A32(O, S) REG(1) " = " REGU(1) " " #O " " S
66*7304104dSAndroid Build Coastguard Worker #define A64(O, S) REG(1) " " #O "= " S
67*7304104dSAndroid Build Coastguard Worker #define J64(D, O, S) "if " D " " #O " " S " goto " JMP(3)
68*7304104dSAndroid Build Coastguard Worker #define LOAD(T) REG(1) " = *(" #T " *)(" REG(2) OFF(3) ")"
69*7304104dSAndroid Build Coastguard Worker #define STORE(T, S) "*(" #T " *)(" REG(1) OFF(3) ") = " S
70*7304104dSAndroid Build Coastguard Worker #define XADD(T, S) "lock *(" #T " *)(" REG(1) OFF(3) ") += " S
71*7304104dSAndroid Build Coastguard Worker #define LDSKB(T, S) "r0 = *(" #T " *)skb[" S "]"
72*7304104dSAndroid Build Coastguard Worker
73*7304104dSAndroid Build Coastguard Worker static void
bswap_bpf_insn(struct bpf_insn * p)74*7304104dSAndroid Build Coastguard Worker bswap_bpf_insn (struct bpf_insn *p)
75*7304104dSAndroid Build Coastguard Worker {
76*7304104dSAndroid Build Coastguard Worker /* Note that the dst_reg and src_reg fields are 4-bit bitfields.
77*7304104dSAndroid Build Coastguard Worker That means these two nibbles are (typically) laid out in the
78*7304104dSAndroid Build Coastguard Worker opposite order between big- and little-endian hosts. This is
79*7304104dSAndroid Build Coastguard Worker not required by any standard, but does happen to be true for
80*7304104dSAndroid Build Coastguard Worker at least ppc, s390, arm and mips as big-endian hosts. */
81*7304104dSAndroid Build Coastguard Worker int t = p->dst_reg;
82*7304104dSAndroid Build Coastguard Worker p->dst_reg = p->src_reg;
83*7304104dSAndroid Build Coastguard Worker p->src_reg = t;
84*7304104dSAndroid Build Coastguard Worker
85*7304104dSAndroid Build Coastguard Worker /* The other 2 and 4 byte fields are trivially converted. */
86*7304104dSAndroid Build Coastguard Worker CONVERT (p->off);
87*7304104dSAndroid Build Coastguard Worker CONVERT (p->imm);
88*7304104dSAndroid Build Coastguard Worker }
89*7304104dSAndroid Build Coastguard Worker
90*7304104dSAndroid Build Coastguard Worker int
bpf_disasm(Ebl * ebl,const uint8_t ** startp,const uint8_t * end,GElf_Addr addr,const char * fmt,DisasmOutputCB_t outcb,DisasmGetSymCB_t symcb,void * outcbarg,void * symcbarg)91*7304104dSAndroid Build Coastguard Worker bpf_disasm (Ebl *ebl, const uint8_t **startp, const uint8_t *end,
92*7304104dSAndroid Build Coastguard Worker GElf_Addr addr, const char *fmt __attribute__((unused)),
93*7304104dSAndroid Build Coastguard Worker DisasmOutputCB_t outcb,
94*7304104dSAndroid Build Coastguard Worker DisasmGetSymCB_t symcb __attribute__((unused)),
95*7304104dSAndroid Build Coastguard Worker void *outcbarg,
96*7304104dSAndroid Build Coastguard Worker void *symcbarg __attribute__((unused)))
97*7304104dSAndroid Build Coastguard Worker {
98*7304104dSAndroid Build Coastguard Worker const bool need_bswap = MY_ELFDATA != ebl->data;
99*7304104dSAndroid Build Coastguard Worker const uint8_t *start = *startp;
100*7304104dSAndroid Build Coastguard Worker char buf[128];
101*7304104dSAndroid Build Coastguard Worker int len, retval = 0;
102*7304104dSAndroid Build Coastguard Worker
103*7304104dSAndroid Build Coastguard Worker while (start + sizeof(struct bpf_insn) <= end)
104*7304104dSAndroid Build Coastguard Worker {
105*7304104dSAndroid Build Coastguard Worker struct bpf_insn i;
106*7304104dSAndroid Build Coastguard Worker unsigned code, class, jmp;
107*7304104dSAndroid Build Coastguard Worker const char *code_fmt;
108*7304104dSAndroid Build Coastguard Worker
109*7304104dSAndroid Build Coastguard Worker memcpy(&i, start, sizeof(struct bpf_insn));
110*7304104dSAndroid Build Coastguard Worker if (need_bswap)
111*7304104dSAndroid Build Coastguard Worker bswap_bpf_insn (&i);
112*7304104dSAndroid Build Coastguard Worker
113*7304104dSAndroid Build Coastguard Worker start += sizeof(struct bpf_insn);
114*7304104dSAndroid Build Coastguard Worker addr += sizeof(struct bpf_insn);
115*7304104dSAndroid Build Coastguard Worker jmp = addr + i.off * sizeof(struct bpf_insn);
116*7304104dSAndroid Build Coastguard Worker
117*7304104dSAndroid Build Coastguard Worker code = i.code;
118*7304104dSAndroid Build Coastguard Worker switch (code)
119*7304104dSAndroid Build Coastguard Worker {
120*7304104dSAndroid Build Coastguard Worker case BPF_LD | BPF_IMM | BPF_DW:
121*7304104dSAndroid Build Coastguard Worker {
122*7304104dSAndroid Build Coastguard Worker struct bpf_insn i2;
123*7304104dSAndroid Build Coastguard Worker uint64_t imm64;
124*7304104dSAndroid Build Coastguard Worker
125*7304104dSAndroid Build Coastguard Worker if (start + sizeof(struct bpf_insn) > end)
126*7304104dSAndroid Build Coastguard Worker {
127*7304104dSAndroid Build Coastguard Worker start -= sizeof(struct bpf_insn);
128*7304104dSAndroid Build Coastguard Worker *startp = start;
129*7304104dSAndroid Build Coastguard Worker goto done;
130*7304104dSAndroid Build Coastguard Worker }
131*7304104dSAndroid Build Coastguard Worker memcpy(&i2, start, sizeof(struct bpf_insn));
132*7304104dSAndroid Build Coastguard Worker if (need_bswap)
133*7304104dSAndroid Build Coastguard Worker bswap_bpf_insn (&i2);
134*7304104dSAndroid Build Coastguard Worker start += sizeof(struct bpf_insn);
135*7304104dSAndroid Build Coastguard Worker addr += sizeof(struct bpf_insn);
136*7304104dSAndroid Build Coastguard Worker
137*7304104dSAndroid Build Coastguard Worker imm64 = (uint32_t)i.imm | ((uint64_t)i2.imm << 32);
138*7304104dSAndroid Build Coastguard Worker switch (i.src_reg)
139*7304104dSAndroid Build Coastguard Worker {
140*7304104dSAndroid Build Coastguard Worker case 0:
141*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = %2$#" PRIx64;
142*7304104dSAndroid Build Coastguard Worker break;
143*7304104dSAndroid Build Coastguard Worker case BPF_PSEUDO_MAP_FD:
144*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = map_fd(%2$#" PRIx64 ")";
145*7304104dSAndroid Build Coastguard Worker break;
146*7304104dSAndroid Build Coastguard Worker default:
147*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = ld_pseudo(%3$d, %2$#" PRIx64 ")";
148*7304104dSAndroid Build Coastguard Worker break;
149*7304104dSAndroid Build Coastguard Worker }
150*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt,
151*7304104dSAndroid Build Coastguard Worker i.dst_reg, imm64, i.src_reg);
152*7304104dSAndroid Build Coastguard Worker }
153*7304104dSAndroid Build Coastguard Worker break;
154*7304104dSAndroid Build Coastguard Worker
155*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_EXIT:
156*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), "exit");
157*7304104dSAndroid Build Coastguard Worker break;
158*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JA:
159*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), "goto " JMP(1), jmp);
160*7304104dSAndroid Build Coastguard Worker break;
161*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_CALL:
162*7304104dSAndroid Build Coastguard Worker code_fmt = "call " IMMS(1);
163*7304104dSAndroid Build Coastguard Worker goto do_imm;
164*7304104dSAndroid Build Coastguard Worker
165*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_END | BPF_TO_LE:
166*7304104dSAndroid Build Coastguard Worker /* The imm field contains {16,32,64}. */
167*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = le" IMMS(2) "(" REG(1) ")";
168*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
169*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_END | BPF_TO_BE:
170*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = be" IMMS(2) "(" REG(1) ")";
171*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
172*7304104dSAndroid Build Coastguard Worker
173*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_ADD | BPF_K:
174*7304104dSAndroid Build Coastguard Worker code_fmt = A32(+, IMMS(2));
175*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
176*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_SUB | BPF_K:
177*7304104dSAndroid Build Coastguard Worker code_fmt = A32(-, IMMS(2));
178*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
179*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_MUL | BPF_K:
180*7304104dSAndroid Build Coastguard Worker code_fmt = A32(*, IMMS(2));
181*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
182*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_DIV | BPF_K:
183*7304104dSAndroid Build Coastguard Worker code_fmt = A32(/, IMMS(2));
184*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
185*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_OR | BPF_K:
186*7304104dSAndroid Build Coastguard Worker code_fmt = A32(|, IMMX(2));
187*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
188*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_AND | BPF_K:
189*7304104dSAndroid Build Coastguard Worker code_fmt = A32(&, IMMX(2));
190*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
191*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_LSH | BPF_K:
192*7304104dSAndroid Build Coastguard Worker code_fmt = A32(<<, IMMS(2));
193*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
194*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_RSH | BPF_K:
195*7304104dSAndroid Build Coastguard Worker code_fmt = A32(>>, IMMS(2));
196*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
197*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_MOD | BPF_K:
198*7304104dSAndroid Build Coastguard Worker code_fmt = A32(%%, IMMS(2));
199*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
200*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_XOR | BPF_K:
201*7304104dSAndroid Build Coastguard Worker code_fmt = A32(^, IMMX(2));
202*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
203*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_MOV | BPF_K:
204*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = " IMMX(2);
205*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
206*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_ARSH | BPF_K:
207*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = (u32)((s32)" REG(1) " >> " IMMS(2) ")";
208*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
209*7304104dSAndroid Build Coastguard Worker
210*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_ADD | BPF_X:
211*7304104dSAndroid Build Coastguard Worker code_fmt = A32(+, REGU(2));
212*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
213*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_SUB | BPF_X:
214*7304104dSAndroid Build Coastguard Worker code_fmt = A32(-, REGU(2));
215*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
216*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_MUL | BPF_X:
217*7304104dSAndroid Build Coastguard Worker code_fmt = A32(*, REGU(2));
218*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
219*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_DIV | BPF_X:
220*7304104dSAndroid Build Coastguard Worker code_fmt = A32(/, REGU(2));
221*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
222*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_OR | BPF_X:
223*7304104dSAndroid Build Coastguard Worker code_fmt = A32(|, REGU(2));
224*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
225*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_AND | BPF_X:
226*7304104dSAndroid Build Coastguard Worker code_fmt = A32(&, REGU(2));
227*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
228*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_LSH | BPF_X:
229*7304104dSAndroid Build Coastguard Worker code_fmt = A32(<<, REGU(2));
230*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
231*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_RSH | BPF_X:
232*7304104dSAndroid Build Coastguard Worker code_fmt = A32(>>, REGU(2));
233*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
234*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_MOD | BPF_X:
235*7304104dSAndroid Build Coastguard Worker code_fmt = A32(%%, REGU(2));
236*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
237*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_XOR | BPF_X:
238*7304104dSAndroid Build Coastguard Worker code_fmt = A32(^, REGU(2));
239*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
240*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_MOV | BPF_X:
241*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = " REGU(2);
242*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
243*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_ARSH | BPF_X:
244*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = (u32)((s32)" REG(1) " >> " REG(2) ")";
245*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
246*7304104dSAndroid Build Coastguard Worker
247*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_ADD | BPF_K:
248*7304104dSAndroid Build Coastguard Worker code_fmt = A64(+, IMMS(2));
249*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
250*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_SUB | BPF_K:
251*7304104dSAndroid Build Coastguard Worker code_fmt = A64(-, IMMS(2));
252*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
253*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_MUL | BPF_K:
254*7304104dSAndroid Build Coastguard Worker code_fmt = A64(*, IMMS(2));
255*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
256*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_DIV | BPF_K:
257*7304104dSAndroid Build Coastguard Worker code_fmt = A64(/, IMMS(2));
258*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
259*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_OR | BPF_K:
260*7304104dSAndroid Build Coastguard Worker code_fmt = A64(|, IMMS(2));
261*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
262*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_AND | BPF_K:
263*7304104dSAndroid Build Coastguard Worker code_fmt = A64(&, IMMS(2));
264*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
265*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_LSH | BPF_K:
266*7304104dSAndroid Build Coastguard Worker code_fmt = A64(<<, IMMS(2));
267*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
268*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_RSH | BPF_K:
269*7304104dSAndroid Build Coastguard Worker code_fmt = A64(>>, IMMS(2));
270*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
271*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_MOD | BPF_K:
272*7304104dSAndroid Build Coastguard Worker code_fmt = A64(%%, IMMS(2));
273*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
274*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_XOR | BPF_K:
275*7304104dSAndroid Build Coastguard Worker code_fmt = A64(^, IMMS(2));
276*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
277*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_MOV | BPF_K:
278*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = " IMMS(2);
279*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
280*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_ARSH | BPF_K:
281*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = (s64)" REG(1) " >> " IMMS(2);
282*7304104dSAndroid Build Coastguard Worker goto do_dst_imm;
283*7304104dSAndroid Build Coastguard Worker
284*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_ADD | BPF_X:
285*7304104dSAndroid Build Coastguard Worker code_fmt = A64(+, REG(2));
286*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
287*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_SUB | BPF_X:
288*7304104dSAndroid Build Coastguard Worker code_fmt = A64(-, REG(2));
289*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
290*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_MUL | BPF_X:
291*7304104dSAndroid Build Coastguard Worker code_fmt = A64(*, REG(2));
292*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
293*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_DIV | BPF_X:
294*7304104dSAndroid Build Coastguard Worker code_fmt = A64(/, REG(2));
295*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
296*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_OR | BPF_X:
297*7304104dSAndroid Build Coastguard Worker code_fmt = A64(|, REG(2));
298*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
299*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_AND | BPF_X:
300*7304104dSAndroid Build Coastguard Worker code_fmt = A64(&, REG(2));
301*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
302*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_LSH | BPF_X:
303*7304104dSAndroid Build Coastguard Worker code_fmt = A64(<<, REG(2));
304*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
305*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_RSH | BPF_X:
306*7304104dSAndroid Build Coastguard Worker code_fmt = A64(>>, REG(2));
307*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
308*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_MOD | BPF_X:
309*7304104dSAndroid Build Coastguard Worker code_fmt = A64(%%, REG(2));
310*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
311*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_XOR | BPF_X:
312*7304104dSAndroid Build Coastguard Worker code_fmt = A64(^, REG(2));
313*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
314*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_MOV | BPF_X:
315*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = " REG(2);
316*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
317*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_ARSH | BPF_X:
318*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = (s64)" REG(1) " >> " REG(2);
319*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
320*7304104dSAndroid Build Coastguard Worker
321*7304104dSAndroid Build Coastguard Worker case BPF_ALU | BPF_NEG:
322*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = (u32)-" REG(1);
323*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
324*7304104dSAndroid Build Coastguard Worker case BPF_ALU64 | BPF_NEG:
325*7304104dSAndroid Build Coastguard Worker code_fmt = REG(1) " = -" REG(1);
326*7304104dSAndroid Build Coastguard Worker goto do_dst_src;
327*7304104dSAndroid Build Coastguard Worker
328*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JEQ | BPF_K:
329*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), ==, IMMS(2));
330*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
331*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JGT | BPF_K:
332*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), >, IMMS(2));
333*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
334*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JGE | BPF_K:
335*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), >=, IMMS(2));
336*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
337*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSET | BPF_K:
338*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), &, IMMS(2));
339*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
340*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JNE | BPF_K:
341*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), !=, IMMS(2));
342*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
343*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSGT | BPF_K:
344*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), >, IMMS(2));
345*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
346*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSGE | BPF_K:
347*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), >=, IMMS(2));
348*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
349*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JLT | BPF_K:
350*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), <, IMMS(2));
351*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
352*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JLE | BPF_K:
353*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), <=, IMMS(2));
354*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
355*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSLT | BPF_K:
356*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), <, IMMS(2));
357*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
358*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSLE | BPF_K:
359*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), <=, IMMS(2));
360*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_jmp;
361*7304104dSAndroid Build Coastguard Worker
362*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JEQ | BPF_X:
363*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), ==, REG(2));
364*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
365*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JGT | BPF_X:
366*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), >, REG(2));
367*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
368*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JGE | BPF_X:
369*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), >=, REG(2));
370*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
371*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSET | BPF_X:
372*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), &, REG(2));
373*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
374*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JNE | BPF_X:
375*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), !=, REG(2));
376*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
377*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSGT | BPF_X:
378*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), >, REGS(2));
379*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
380*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSGE | BPF_X:
381*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), >=, REGS(2));
382*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
383*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JLT | BPF_X:
384*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), <, REG(2));
385*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
386*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JLE | BPF_X:
387*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REG(1), <=, REG(2));
388*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
389*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSLT | BPF_X:
390*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), <, REGS(2));
391*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
392*7304104dSAndroid Build Coastguard Worker case BPF_JMP | BPF_JSLE | BPF_X:
393*7304104dSAndroid Build Coastguard Worker code_fmt = J64(REGS(1), <=, REGS(2));
394*7304104dSAndroid Build Coastguard Worker goto do_dst_src_jmp;
395*7304104dSAndroid Build Coastguard Worker
396*7304104dSAndroid Build Coastguard Worker case BPF_LDX | BPF_MEM | BPF_B:
397*7304104dSAndroid Build Coastguard Worker code_fmt = LOAD(u8);
398*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
399*7304104dSAndroid Build Coastguard Worker case BPF_LDX | BPF_MEM | BPF_H:
400*7304104dSAndroid Build Coastguard Worker code_fmt = LOAD(u16);
401*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
402*7304104dSAndroid Build Coastguard Worker case BPF_LDX | BPF_MEM | BPF_W:
403*7304104dSAndroid Build Coastguard Worker code_fmt = LOAD(u32);
404*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
405*7304104dSAndroid Build Coastguard Worker case BPF_LDX | BPF_MEM | BPF_DW:
406*7304104dSAndroid Build Coastguard Worker code_fmt = LOAD(u64);
407*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
408*7304104dSAndroid Build Coastguard Worker
409*7304104dSAndroid Build Coastguard Worker case BPF_STX | BPF_MEM | BPF_B:
410*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u8, REG(2));
411*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
412*7304104dSAndroid Build Coastguard Worker case BPF_STX | BPF_MEM | BPF_H:
413*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u16, REG(2));
414*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
415*7304104dSAndroid Build Coastguard Worker case BPF_STX | BPF_MEM | BPF_W:
416*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u32, REG(2));
417*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
418*7304104dSAndroid Build Coastguard Worker case BPF_STX | BPF_MEM | BPF_DW:
419*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u64, REG(2));
420*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
421*7304104dSAndroid Build Coastguard Worker
422*7304104dSAndroid Build Coastguard Worker case BPF_STX | BPF_XADD | BPF_W:
423*7304104dSAndroid Build Coastguard Worker code_fmt = XADD(u32, REG(2));
424*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
425*7304104dSAndroid Build Coastguard Worker case BPF_STX | BPF_XADD | BPF_DW:
426*7304104dSAndroid Build Coastguard Worker code_fmt = XADD(u64, REG(2));
427*7304104dSAndroid Build Coastguard Worker goto do_dst_src_off;
428*7304104dSAndroid Build Coastguard Worker
429*7304104dSAndroid Build Coastguard Worker case BPF_ST | BPF_MEM | BPF_B:
430*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u8, IMMS(2));
431*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_off;
432*7304104dSAndroid Build Coastguard Worker case BPF_ST | BPF_MEM | BPF_H:
433*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u16, IMMS(2));
434*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_off;
435*7304104dSAndroid Build Coastguard Worker case BPF_ST | BPF_MEM | BPF_W:
436*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u32, IMMS(2));
437*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_off;
438*7304104dSAndroid Build Coastguard Worker case BPF_ST | BPF_MEM | BPF_DW:
439*7304104dSAndroid Build Coastguard Worker code_fmt = STORE(u64, IMMS(2));
440*7304104dSAndroid Build Coastguard Worker goto do_dst_imm_off;
441*7304104dSAndroid Build Coastguard Worker
442*7304104dSAndroid Build Coastguard Worker case BPF_LD | BPF_ABS | BPF_B:
443*7304104dSAndroid Build Coastguard Worker code_fmt = LDSKB(u8, IMMS(1));
444*7304104dSAndroid Build Coastguard Worker goto do_imm;
445*7304104dSAndroid Build Coastguard Worker case BPF_LD | BPF_ABS | BPF_H:
446*7304104dSAndroid Build Coastguard Worker code_fmt = LDSKB(u16, IMMS(1));
447*7304104dSAndroid Build Coastguard Worker goto do_imm;
448*7304104dSAndroid Build Coastguard Worker case BPF_LD | BPF_ABS | BPF_W:
449*7304104dSAndroid Build Coastguard Worker code_fmt = LDSKB(u32, IMMS(1));
450*7304104dSAndroid Build Coastguard Worker goto do_imm;
451*7304104dSAndroid Build Coastguard Worker
452*7304104dSAndroid Build Coastguard Worker case BPF_LD | BPF_IND | BPF_B:
453*7304104dSAndroid Build Coastguard Worker code_fmt = LDSKB(u8, REG(1) "+" IMMS(2));
454*7304104dSAndroid Build Coastguard Worker goto do_src_imm;
455*7304104dSAndroid Build Coastguard Worker case BPF_LD | BPF_IND | BPF_H:
456*7304104dSAndroid Build Coastguard Worker code_fmt = LDSKB(u16, REG(1) "+" IMMS(2));
457*7304104dSAndroid Build Coastguard Worker goto do_src_imm;
458*7304104dSAndroid Build Coastguard Worker case BPF_LD | BPF_IND | BPF_W:
459*7304104dSAndroid Build Coastguard Worker code_fmt = LDSKB(u32, REG(1) "+" IMMS(2));
460*7304104dSAndroid Build Coastguard Worker goto do_src_imm;
461*7304104dSAndroid Build Coastguard Worker
462*7304104dSAndroid Build Coastguard Worker do_imm:
463*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt, i.imm);
464*7304104dSAndroid Build Coastguard Worker break;
465*7304104dSAndroid Build Coastguard Worker do_dst_imm:
466*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm);
467*7304104dSAndroid Build Coastguard Worker break;
468*7304104dSAndroid Build Coastguard Worker do_src_imm:
469*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt, i.src_reg, i.imm);
470*7304104dSAndroid Build Coastguard Worker break;
471*7304104dSAndroid Build Coastguard Worker do_dst_src:
472*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.src_reg);
473*7304104dSAndroid Build Coastguard Worker break;
474*7304104dSAndroid Build Coastguard Worker do_dst_imm_jmp:
475*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm, jmp);
476*7304104dSAndroid Build Coastguard Worker break;
477*7304104dSAndroid Build Coastguard Worker do_dst_src_jmp:
478*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt,
479*7304104dSAndroid Build Coastguard Worker i.dst_reg, i.src_reg, jmp);
480*7304104dSAndroid Build Coastguard Worker break;
481*7304104dSAndroid Build Coastguard Worker do_dst_imm_off:
482*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm, i.off);
483*7304104dSAndroid Build Coastguard Worker break;
484*7304104dSAndroid Build Coastguard Worker do_dst_src_off:
485*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), code_fmt,
486*7304104dSAndroid Build Coastguard Worker i.dst_reg, i.src_reg, i.off);
487*7304104dSAndroid Build Coastguard Worker break;
488*7304104dSAndroid Build Coastguard Worker
489*7304104dSAndroid Build Coastguard Worker default:
490*7304104dSAndroid Build Coastguard Worker class = BPF_CLASS(code);
491*7304104dSAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), "invalid class %s",
492*7304104dSAndroid Build Coastguard Worker class_string[class]);
493*7304104dSAndroid Build Coastguard Worker break;
494*7304104dSAndroid Build Coastguard Worker }
495*7304104dSAndroid Build Coastguard Worker
496*7304104dSAndroid Build Coastguard Worker *startp = start;
497*7304104dSAndroid Build Coastguard Worker retval = outcb (buf, len, outcbarg);
498*7304104dSAndroid Build Coastguard Worker if (retval != 0)
499*7304104dSAndroid Build Coastguard Worker goto done;
500*7304104dSAndroid Build Coastguard Worker }
501*7304104dSAndroid Build Coastguard Worker
502*7304104dSAndroid Build Coastguard Worker done:
503*7304104dSAndroid Build Coastguard Worker return retval;
504*7304104dSAndroid Build Coastguard Worker }
505