diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2019-04-09 17:20:15 -0400 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2019-04-09 20:05:47 -0400 |
commit | 817998afa038c156bbc1a6e69c48aa26282cc41f (patch) | |
tree | 0b9dd4132343ed490f7162d3ab75690304b2f722 /tools/bpf/bpftool | |
parent | 1713d68b3bf039d029afd74653c9325f5003ccbe (diff) |
bpf: bpftool support for dumping data/bss/rodata sections
Add the ability to bpftool to handle BTF Var and DataSec kinds
in order to dump them out of btf_dumper_type(). The value has a
single object with the section name, which itself holds an array
of variables it dumps. A single variable is an object by itself
printed along with its name. From there further type information
is dumped along with corresponding value information.
Example output from .rodata:
# ./bpftool m d i 150
[{
"value": {
".rodata": [{
"load_static_data.bar": 18446744073709551615
},{
"num2": 24
},{
"num5": 43947
},{
"num6": 171
},{
"str0": [97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,0,0,0,0,0,0
]
},{
"struct0": {
"a": 42,
"b": 4278120431,
"c": 1229782938247303441
}
},{
"struct2": {
"a": 0,
"b": 0,
"c": 0
}
}
]
}
}
]
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/bpf/bpftool')
-rw-r--r-- | tools/bpf/bpftool/btf_dumper.c | 59 | ||||
-rw-r--r-- | tools/bpf/bpftool/map.c | 10 |
2 files changed, 65 insertions, 4 deletions
diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c index e63bce0755eb..8cafb9b31467 100644 --- a/tools/bpf/bpftool/btf_dumper.c +++ b/tools/bpf/bpftool/btf_dumper.c | |||
@@ -309,6 +309,48 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id, | |||
309 | return ret; | 309 | return ret; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int btf_dumper_var(const struct btf_dumper *d, __u32 type_id, | ||
313 | __u8 bit_offset, const void *data) | ||
314 | { | ||
315 | const struct btf_type *t = btf__type_by_id(d->btf, type_id); | ||
316 | int ret; | ||
317 | |||
318 | jsonw_start_object(d->jw); | ||
319 | jsonw_name(d->jw, btf__name_by_offset(d->btf, t->name_off)); | ||
320 | ret = btf_dumper_do_type(d, t->type, bit_offset, data); | ||
321 | jsonw_end_object(d->jw); | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static int btf_dumper_datasec(const struct btf_dumper *d, __u32 type_id, | ||
327 | const void *data) | ||
328 | { | ||
329 | struct btf_var_secinfo *vsi; | ||
330 | const struct btf_type *t; | ||
331 | int ret = 0, i, vlen; | ||
332 | |||
333 | t = btf__type_by_id(d->btf, type_id); | ||
334 | if (!t) | ||
335 | return -EINVAL; | ||
336 | |||
337 | vlen = BTF_INFO_VLEN(t->info); | ||
338 | vsi = (struct btf_var_secinfo *)(t + 1); | ||
339 | |||
340 | jsonw_start_object(d->jw); | ||
341 | jsonw_name(d->jw, btf__name_by_offset(d->btf, t->name_off)); | ||
342 | jsonw_start_array(d->jw); | ||
343 | for (i = 0; i < vlen; i++) { | ||
344 | ret = btf_dumper_do_type(d, vsi[i].type, 0, data + vsi[i].offset); | ||
345 | if (ret) | ||
346 | break; | ||
347 | } | ||
348 | jsonw_end_array(d->jw); | ||
349 | jsonw_end_object(d->jw); | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
312 | static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id, | 354 | static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id, |
313 | __u8 bit_offset, const void *data) | 355 | __u8 bit_offset, const void *data) |
314 | { | 356 | { |
@@ -341,6 +383,10 @@ static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id, | |||
341 | case BTF_KIND_CONST: | 383 | case BTF_KIND_CONST: |
342 | case BTF_KIND_RESTRICT: | 384 | case BTF_KIND_RESTRICT: |
343 | return btf_dumper_modifier(d, type_id, bit_offset, data); | 385 | return btf_dumper_modifier(d, type_id, bit_offset, data); |
386 | case BTF_KIND_VAR: | ||
387 | return btf_dumper_var(d, type_id, bit_offset, data); | ||
388 | case BTF_KIND_DATASEC: | ||
389 | return btf_dumper_datasec(d, type_id, data); | ||
344 | default: | 390 | default: |
345 | jsonw_printf(d->jw, "(unsupported-kind"); | 391 | jsonw_printf(d->jw, "(unsupported-kind"); |
346 | return -EINVAL; | 392 | return -EINVAL; |
@@ -377,6 +423,7 @@ static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id, | |||
377 | { | 423 | { |
378 | const struct btf_type *proto_type; | 424 | const struct btf_type *proto_type; |
379 | const struct btf_array *array; | 425 | const struct btf_array *array; |
426 | const struct btf_var *var; | ||
380 | const struct btf_type *t; | 427 | const struct btf_type *t; |
381 | 428 | ||
382 | if (!type_id) { | 429 | if (!type_id) { |
@@ -440,6 +487,18 @@ static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id, | |||
440 | if (pos == -1) | 487 | if (pos == -1) |
441 | return -1; | 488 | return -1; |
442 | break; | 489 | break; |
490 | case BTF_KIND_VAR: | ||
491 | var = (struct btf_var *)(t + 1); | ||
492 | if (var->linkage == BTF_VAR_STATIC) | ||
493 | BTF_PRINT_ARG("static "); | ||
494 | BTF_PRINT_TYPE(t->type); | ||
495 | BTF_PRINT_ARG(" %s", | ||
496 | btf__name_by_offset(btf, t->name_off)); | ||
497 | break; | ||
498 | case BTF_KIND_DATASEC: | ||
499 | BTF_PRINT_ARG("section (\"%s\") ", | ||
500 | btf__name_by_offset(btf, t->name_off)); | ||
501 | break; | ||
443 | case BTF_KIND_UNKN: | 502 | case BTF_KIND_UNKN: |
444 | default: | 503 | default: |
445 | return -1; | 504 | return -1; |
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index e0c650d91784..e96903078991 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c | |||
@@ -153,11 +153,13 @@ static int do_dump_btf(const struct btf_dumper *d, | |||
153 | /* start of key-value pair */ | 153 | /* start of key-value pair */ |
154 | jsonw_start_object(d->jw); | 154 | jsonw_start_object(d->jw); |
155 | 155 | ||
156 | jsonw_name(d->jw, "key"); | 156 | if (map_info->btf_key_type_id) { |
157 | jsonw_name(d->jw, "key"); | ||
157 | 158 | ||
158 | ret = btf_dumper_type(d, map_info->btf_key_type_id, key); | 159 | ret = btf_dumper_type(d, map_info->btf_key_type_id, key); |
159 | if (ret) | 160 | if (ret) |
160 | goto err_end_obj; | 161 | goto err_end_obj; |
162 | } | ||
161 | 163 | ||
162 | if (!map_is_per_cpu(map_info->type)) { | 164 | if (!map_is_per_cpu(map_info->type)) { |
163 | jsonw_name(d->jw, "value"); | 165 | jsonw_name(d->jw, "value"); |