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