Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/bpf/disasm_helpers.c
26285 views
1
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2
3
#include <bpf/bpf.h>
4
#include "disasm.h"
5
6
struct print_insn_context {
7
char scratch[16];
8
char *buf;
9
size_t sz;
10
};
11
12
static 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
22
static 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
38
struct 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
}
70
71