brintos

brintos / linux-shallow public Read only

0
0
Text · 1.8 KiB · f529f1c Raw
70 lines · c
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 original27	 * imm to insn->off and changes insn->imm to be an index of28	 * 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) ' prefix55	 * 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}70