Skip to content

Commit f38424e

Browse files
committed
bpftool: Dump oracle maps
Signed-off-by: Paul Chaignon <[email protected]>
1 parent 51b9ba4 commit f38424e

File tree

4 files changed

+168
-1
lines changed

4 files changed

+168
-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: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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+
}
72+
printf("\n");
73+
num_elems++;
74+
prev_key = &key;
75+
}
76+
77+
printf("Found %u state%s\n", num_elems,
78+
num_elems != 1 ? "s" : "");
79+
80+
close(fd);
81+
return err;
82+
}
83+
84+
static int do_dump(int argc, char **argv)
85+
{
86+
struct bpf_map_info info = {};
87+
__u32 len = sizeof(info);
88+
int nb_fds, i, err;
89+
int *fds = NULL;
90+
91+
fds = malloc(sizeof(int));
92+
if (!fds) {
93+
p_err("mem alloc failed");
94+
return -1;
95+
}
96+
nb_fds = map_parse_fds(&argc, &argv, &fds, BPF_F_RDONLY);
97+
if (nb_fds < 1)
98+
goto exit_free;
99+
100+
for (i = 0; i < nb_fds; i++) {
101+
if (bpf_map_get_info_by_fd(fds[i], &info, &len)) {
102+
p_err("can't get map info: %s", strerror(errno));
103+
break;
104+
}
105+
if (info.type != BPF_MAP_TYPE_ARRAY || info.key_size != sizeof(__u32) ||
106+
info.value_size != sizeof(struct bpf_oracle_state)) {
107+
p_err("not an oracle map");
108+
break;
109+
}
110+
err = oracle_map_dump(fds[i], &info, nb_fds > 1);
111+
if (i != nb_fds - 1)
112+
printf("\n");
113+
114+
if (err)
115+
break;
116+
close(fds[i]);
117+
}
118+
119+
for (; i < nb_fds; i++)
120+
close(fds[i]);
121+
exit_free:
122+
free(fds);
123+
return 0;
124+
}
125+
126+
static int do_help(int argc, char **argv)
127+
{
128+
if (json_output) {
129+
jsonw_null(json_wtr);
130+
return 0;
131+
}
132+
133+
fprintf(stderr,
134+
"Usage: %1$s %2$s dump MAP\n"
135+
" %1$s %2$s help\n"
136+
"\n"
137+
" " HELP_SPEC_MAP "\n"
138+
" " HELP_SPEC_OPTIONS " |\n"
139+
" {-f|--bpffs} | {-n|--nomount} }\n"
140+
"",
141+
bin_name, argv[-2]);
142+
143+
return 0;
144+
}
145+
146+
static const struct cmd cmds[] = {
147+
{ "help", do_help },
148+
{ "dump", do_dump },
149+
{ 0 }
150+
};
151+
152+
int do_oracle(int argc, char **argv)
153+
{
154+
return cmd_select(cmds, argc, argv, do_help);
155+
}

tools/include/uapi/linux/bpf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,16 @@ enum {
13341334
#define BPF_PSEUDO_MAP_VALUE 2
13351335
#define BPF_PSEUDO_MAP_IDX_VALUE 6
13361336

1337+
/* Internal only.
1338+
* insn[0].dst_reg: 0
1339+
* insn[0].src_reg: BPF_PSEUDO_MAP_ORACLE
1340+
* insn[0].imm: address of oracle state list
1341+
* insn[1].imm: address of oracle state list
1342+
* insn[0].off: 0
1343+
* insn[1].off: 0
1344+
*/
1345+
#define BPF_PSEUDO_MAP_ORACLE 7
1346+
13371347
/* insn[0].src_reg: BPF_PSEUDO_BTF_ID
13381348
* insn[0].imm: kernel btd id of VAR
13391349
* insn[1].imm: 0

0 commit comments

Comments
 (0)