xref: /aosp_15_r20/external/elfutils/libcpu/bpf_disasm.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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