Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
 1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 2
 3#include <bpf/bpf.h>
 4#include "disasm.h"
 5
 6struct print_insn_context {
 7	char scratch[16];
 8	char *buf;
 9	size_t sz;
10};
11
12static void print_insn_cb(void *private_data, const char *fmt, ...)
13{
14	struct print_insn_context *ctx = private_data;
15	va_list args;
16
17	va_start(args, fmt);
18	vsnprintf(ctx->buf, ctx->sz, fmt, args);
19	va_end(args);
20}
21
22static const char *print_call_cb(void *private_data, const struct bpf_insn *insn)
23{
24	struct print_insn_context *ctx = private_data;
25
26	/* For pseudo calls verifier.c:jit_subprogs() hides original
27	 * imm to insn->off and changes insn->imm to be an index of
28	 * the subprog instead.
29	 */
30	if (insn->src_reg == BPF_PSEUDO_CALL) {
31		snprintf(ctx->scratch, sizeof(ctx->scratch), "%+d", insn->off);
32		return ctx->scratch;
33	}
34
35	return NULL;
36}
37
38struct bpf_insn *disasm_insn(struct bpf_insn *insn, char *buf, size_t buf_sz)
39{
40	struct print_insn_context ctx = {
41		.buf = buf,
42		.sz = buf_sz,
43	};
44	struct bpf_insn_cbs cbs = {
45		.cb_print	= print_insn_cb,
46		.cb_call	= print_call_cb,
47		.private_data	= &ctx,
48	};
49	char *tmp, *pfx_end, *sfx_start;
50	bool double_insn;
51	int len;
52
53	print_bpf_insn(&cbs, insn, true);
54	/* We share code with kernel BPF disassembler, it adds '(FF) ' prefix
55	 * for each instruction (FF stands for instruction `code` byte).
56	 * Remove the prefix inplace, and also simplify call instructions.
57	 * E.g.: "(85) call foo#10" -> "call foo".
58	 * Also remove newline in the end (the 'max(strlen(buf) - 1, 0)' thing).
59	 */
60	pfx_end = buf + 5;
61	sfx_start = buf + max((int)strlen(buf) - 1, 0);
62	if (strncmp(pfx_end, "call ", 5) == 0 && (tmp = strrchr(buf, '#')))
63		sfx_start = tmp;
64	len = sfx_start - pfx_end;
65	memmove(buf, pfx_end, len);
66	buf[len] = 0;
67	double_insn = insn->code == (BPF_LD | BPF_IMM | BPF_DW);
68	return insn + (double_insn ? 2 : 1);
69}