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