Skip to content

Commit 3ab0d87

Browse files
pchaignoKernel Patches Daemon
authored andcommitted
bpftool: Dump oracle maps
This patch introduces minimum support in bpftool to dump and format the contents of inner oracle maps. This new "bpftool oracle dump" command is only meant to help demo and debug previous commits and is at the very least missing support for JSON output. The current output looks like: # ./bpftool oracle dump id 22 State 0: R0=scalar(u64=[0; 18446744073709551615], s64=[-9223372036854775808; 9223372036854775807], u32=[0; 4294967295], s32=[-2147483648; 2147483647], var_off=(0; 0xffffffffffffffff) R6=scalar(u64=[4294967252; 4294967252], s64=[4294967252; 4294967252], u32=[4294967252; 4294967252], s32=[-44; -44], var_off=(0xffffffd4; 0) Found 1 state Signed-off-by: Paul Chaignon <[email protected]>
1 parent 22fbe89 commit 3ab0d87

File tree

4 files changed

+167
-1
lines changed

4 files changed

+167
-1
lines changed

tools/bpf/bpftool/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static int do_help(int argc, char **argv)
6464
" %s batch file FILE\n"
6565
" %s version\n"
6666
"\n"
67-
" OBJECT := { prog | map | link | cgroup | perf | net | feature | btf | gen | struct_ops | iter | token }\n"
67+
" OBJECT := { prog | map | link | cgroup | perf | net | feature | btf | gen | struct_ops | iter | token | oracle }\n"
6868
" " HELP_SPEC_OPTIONS " |\n"
6969
" {-V|--version} }\n"
7070
"",
@@ -81,6 +81,7 @@ static const struct cmd commands[] = {
8181
{ "batch", do_batch },
8282
{ "prog", do_prog },
8383
{ "map", do_map },
84+
{ "oracle", do_oracle },
8485
{ "link", do_link },
8586
{ "cgroup", do_cgroup },
8687
{ "perf", do_perf },

tools/bpf/bpftool/main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ int do_btf(int argc, char **argv);
166166
/* non-bootstrap only commands */
167167
int do_prog(int argc, char **arg) __weak;
168168
int do_map(int argc, char **arg) __weak;
169+
int do_oracle(int argc, char **arg) __weak;
169170
int do_link(int argc, char **arg) __weak;
170171
int do_event_pipe(int argc, char **argv) __weak;
171172
int do_cgroup(int argc, char **arg) __weak;

tools/bpf/bpftool/oracle.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
3+
#include "main.h"
4+
5+
struct tnum {
6+
__u64 value;
7+
__u64 mask;
8+
};
9+
10+
struct bpf_reg_oracle_state {
11+
bool scalar;
12+
bool ptr_not_null;
13+
14+
struct tnum var_off;
15+
__s64 smin_value;
16+
__s64 smax_value;
17+
__u64 umin_value;
18+
__u64 umax_value;
19+
__s32 s32_min_value;
20+
__s32 s32_max_value;
21+
__u32 u32_min_value;
22+
__u32 u32_max_value;
23+
};
24+
25+
struct bpf_oracle_state {
26+
struct bpf_reg_oracle_state regs[MAX_BPF_REG - 1];
27+
};
28+
29+
static void print_register_state(int i, struct bpf_reg_oracle_state *reg)
30+
{
31+
if (!reg->scalar && !reg->ptr_not_null)
32+
return;
33+
34+
printf("R%d=", i);
35+
if (reg->scalar) {
36+
printf("scalar(u64=[%llu; %llu], s64=[%lld; %lld], u32=[%u; %u], s32=[%d; %d]",
37+
reg->umin_value, reg->umax_value, reg->smin_value, reg->smax_value,
38+
reg->u32_min_value, reg->u32_max_value, reg->s32_min_value,
39+
reg->s32_max_value);
40+
printf(", var_off=(%#llx; %#llx)", reg->var_off.value, reg->var_off.mask);
41+
} else if (reg->ptr_not_null) {
42+
printf("ptr");
43+
} else {
44+
printf("unknown");
45+
}
46+
printf("\n");
47+
}
48+
49+
static int
50+
oracle_map_dump(int fd, struct bpf_map_info *info, bool show_header)
51+
{
52+
struct bpf_oracle_state value = {};
53+
unsigned int num_elems = 0;
54+
__u32 key, *prev_key = NULL;
55+
int err, i;
56+
57+
while (true) {
58+
err = bpf_map_get_next_key(fd, prev_key, &key);
59+
if (err) {
60+
if (errno == ENOENT)
61+
err = 0;
62+
break;
63+
}
64+
if (bpf_map_lookup_elem(fd, &key, &value)) {
65+
printf("<no entry>");
66+
continue;
67+
}
68+
printf("State %u:\n", key);
69+
for (i = 0; i < MAX_BPF_REG - 1; i++)
70+
print_register_state(i, &value.regs[i]);
71+
printf("\n");
72+
num_elems++;
73+
prev_key = &key;
74+
}
75+
76+
printf("Found %u state%s\n", num_elems,
77+
num_elems != 1 ? "s" : "");
78+
79+
close(fd);
80+
return err;
81+
}
82+
83+
static int do_dump(int argc, char **argv)
84+
{
85+
struct bpf_map_info info = {};
86+
__u32 len = sizeof(info);
87+
int nb_fds, i, err;
88+
int *fds = NULL;
89+
90+
fds = malloc(sizeof(int));
91+
if (!fds) {
92+
p_err("mem alloc failed");
93+
return -1;
94+
}
95+
nb_fds = map_parse_fds(&argc, &argv, &fds, BPF_F_RDONLY);
96+
if (nb_fds < 1)
97+
goto exit_free;
98+
99+
for (i = 0; i < nb_fds; i++) {
100+
if (bpf_map_get_info_by_fd(fds[i], &info, &len)) {
101+
p_err("can't get map info: %s", strerror(errno));
102+
break;
103+
}
104+
if (info.type != BPF_MAP_TYPE_ARRAY || info.key_size != sizeof(__u32) ||
105+
info.value_size != sizeof(struct bpf_oracle_state)) {
106+
p_err("not an oracle map");
107+
break;
108+
}
109+
err = oracle_map_dump(fds[i], &info, nb_fds > 1);
110+
if (i != nb_fds - 1)
111+
printf("\n");
112+
113+
if (err)
114+
break;
115+
close(fds[i]);
116+
}
117+
118+
for (; i < nb_fds; i++)
119+
close(fds[i]);
120+
exit_free:
121+
free(fds);
122+
return 0;
123+
}
124+
125+
static int do_help(int argc, char **argv)
126+
{
127+
if (json_output) {
128+
jsonw_null(json_wtr);
129+
return 0;
130+
}
131+
132+
fprintf(stderr,
133+
"Usage: %1$s %2$s dump MAP\n"
134+
" %1$s %2$s help\n"
135+
"\n"
136+
" " HELP_SPEC_MAP "\n"
137+
" " HELP_SPEC_OPTIONS " |\n"
138+
" {-f|--bpffs} | {-n|--nomount} }\n"
139+
"",
140+
bin_name, argv[-2]);
141+
142+
return 0;
143+
}
144+
145+
static const struct cmd cmds[] = {
146+
{ "help", do_help },
147+
{ "dump", do_dump },
148+
{ 0 }
149+
};
150+
151+
int do_oracle(int argc, char **argv)
152+
{
153+
return cmd_select(cmds, argc, argv, do_help);
154+
}

tools/include/uapi/linux/bpf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,16 @@ enum {
13451345
#define BPF_PSEUDO_MAP_VALUE 2
13461346
#define BPF_PSEUDO_MAP_IDX_VALUE 6
13471347

1348+
/* Internal only.
1349+
* insn[0].dst_reg: 0
1350+
* insn[0].src_reg: BPF_PSEUDO_MAP_ORACLE
1351+
* insn[0].imm: address of oracle state list
1352+
* insn[1].imm: address of oracle state list
1353+
* insn[0].off: 0
1354+
* insn[1].off: 0
1355+
*/
1356+
#define BPF_PSEUDO_MAP_ORACLE 7
1357+
13481358
/* insn[0].src_reg: BPF_PSEUDO_BTF_ID
13491359
* insn[0].imm: kernel btd id of VAR
13501360
* insn[1].imm: 0

0 commit comments

Comments
 (0)