Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Daniel Borkmann and committed by
Alexei Starovoitov
817998af 1713d68b

+65 -4
+59
tools/bpf/bpftool/btf_dumper.c
··· 309 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 354 static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id, 313 355 __u8 bit_offset, const void *data) 314 356 { ··· 383 341 case BTF_KIND_CONST: 384 342 case BTF_KIND_RESTRICT: 385 343 return btf_dumper_modifier(d, type_id, bit_offset, data); 344 + case BTF_KIND_VAR: 345 + return btf_dumper_var(d, type_id, bit_offset, data); 346 + case BTF_KIND_DATASEC: 347 + return btf_dumper_datasec(d, type_id, data); 386 348 default: 387 349 jsonw_printf(d->jw, "(unsupported-kind"); 388 350 return -EINVAL; ··· 423 377 { 424 378 const struct btf_type *proto_type; 425 379 const struct btf_array *array; 380 + const struct btf_var *var; 426 381 const struct btf_type *t; 427 382 428 383 if (!type_id) { ··· 486 439 pos = btf_dump_func(btf, func_sig, proto_type, t, pos, size); 487 440 if (pos == -1) 488 441 return -1; 442 + break; 443 + case BTF_KIND_VAR: 444 + var = (struct btf_var *)(t + 1); 445 + if (var->linkage == BTF_VAR_STATIC) 446 + BTF_PRINT_ARG("static "); 447 + BTF_PRINT_TYPE(t->type); 448 + BTF_PRINT_ARG(" %s", 449 + btf__name_by_offset(btf, t->name_off)); 450 + break; 451 + case BTF_KIND_DATASEC: 452 + BTF_PRINT_ARG("section (\"%s\") ", 453 + btf__name_by_offset(btf, t->name_off)); 489 454 break; 490 455 case BTF_KIND_UNKN: 491 456 default:
+6 -4
tools/bpf/bpftool/map.c
··· 153 153 /* start of key-value pair */ 154 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 - if (ret) 160 - goto err_end_obj; 159 + ret = btf_dumper_type(d, map_info->btf_key_type_id, key); 160 + if (ret) 161 + goto err_end_obj; 162 + } 161 163 162 164 if (!map_is_per_cpu(map_info->type)) { 163 165 jsonw_name(d->jw, "value");