Centos-kernel-stream-9/tools/bpf/bpftool/btf.c

1343 lines
30 KiB
C
Raw Normal View History

// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2019 Facebook */
#include <errno.h>
#include <fcntl.h>
#include <linux/err.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <linux/btf.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <bpf/bpf.h>
#include <bpf/btf.h>
#include <bpf/hashmap.h>
#include <bpf/libbpf.h>
#include "json_writer.h"
#include "main.h"
#define KFUNC_DECL_TAG "bpf_kfunc"
static const char * const btf_kind_str[NR_BTF_KINDS] = {
[BTF_KIND_UNKN] = "UNKNOWN",
[BTF_KIND_INT] = "INT",
[BTF_KIND_PTR] = "PTR",
[BTF_KIND_ARRAY] = "ARRAY",
[BTF_KIND_STRUCT] = "STRUCT",
[BTF_KIND_UNION] = "UNION",
[BTF_KIND_ENUM] = "ENUM",
[BTF_KIND_FWD] = "FWD",
[BTF_KIND_TYPEDEF] = "TYPEDEF",
[BTF_KIND_VOLATILE] = "VOLATILE",
[BTF_KIND_CONST] = "CONST",
[BTF_KIND_RESTRICT] = "RESTRICT",
[BTF_KIND_FUNC] = "FUNC",
[BTF_KIND_FUNC_PROTO] = "FUNC_PROTO",
[BTF_KIND_VAR] = "VAR",
[BTF_KIND_DATASEC] = "DATASEC",
[BTF_KIND_FLOAT] = "FLOAT",
bpf: Rename BTF_KIND_TAG to BTF_KIND_DECL_TAG Bugzilla: http://bugzilla.redhat.com/2069045 commit 223f903e9c832699f4e5f422281a60756c1c6cfe Author: Yonghong Song <yhs@fb.com> Date: Tue Oct 12 09:48:38 2021 -0700 bpf: Rename BTF_KIND_TAG to BTF_KIND_DECL_TAG Patch set [1] introduced BTF_KIND_TAG to allow tagging declarations for struct/union, struct/union field, var, func and func arguments and these tags will be encoded into dwarf. They are also encoded to btf by llvm for the bpf target. After BTF_KIND_TAG is introduced, we intended to use it for kernel __user attributes. But kernel __user is actually a type attribute. Upstream and internal discussion showed it is not a good idea to mix declaration attribute and type attribute. So we proposed to introduce btf_type_tag as a type attribute and existing btf_tag renamed to btf_decl_tag ([2]). This patch renamed BTF_KIND_TAG to BTF_KIND_DECL_TAG and some other declarations with *_tag to *_decl_tag to make it clear the tag is for declaration. In the future, BTF_KIND_TYPE_TAG might be introduced per [3]. [1] https://lore.kernel.org/bpf/20210914223004.244411-1-yhs@fb.com/ [2] https://reviews.llvm.org/D111588 [3] https://reviews.llvm.org/D111199 Fixes: b5ea834dde6b ("bpf: Support for new btf kind BTF_KIND_TAG") Fixes: 5b84bd10363e ("libbpf: Add support for BTF_KIND_TAG") Fixes: 5c07f2fec003 ("bpftool: Add support for BTF_KIND_TAG") Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20211012164838.3345699-1-yhs@fb.com Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
2022-04-26 09:29:28 +00:00
[BTF_KIND_DECL_TAG] = "DECL_TAG",
[BTF_KIND_TYPE_TAG] = "TYPE_TAG",
[BTF_KIND_ENUM64] = "ENUM64",
};
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
struct sort_datum {
int index;
int type_rank;
const char *sort_name;
const char *own_name;
__u64 disambig_hash;
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
};
static const char *btf_int_enc_str(__u8 encoding)
{
switch (encoding) {
case 0:
return "(none)";
case BTF_INT_SIGNED:
return "SIGNED";
case BTF_INT_CHAR:
return "CHAR";
case BTF_INT_BOOL:
return "BOOL";
default:
return "UNKN";
}
}
static const char *btf_var_linkage_str(__u32 linkage)
{
switch (linkage) {
case BTF_VAR_STATIC:
return "static";
case BTF_VAR_GLOBAL_ALLOCATED:
return "global";
case BTF_VAR_GLOBAL_EXTERN:
return "extern";
default:
return "(unknown)";
}
}
static const char *btf_func_linkage_str(const struct btf_type *t)
{
switch (btf_vlen(t)) {
case BTF_FUNC_STATIC:
return "static";
case BTF_FUNC_GLOBAL:
return "global";
case BTF_FUNC_EXTERN:
return "extern";
default:
return "(unknown)";
}
}
static const char *btf_str(const struct btf *btf, __u32 off)
{
if (!off)
return "(anon)";
return btf__name_by_offset(btf, off) ? : "(invalid)";
}
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
static int btf_kind_safe(int kind)
{
return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN;
}
static int dump_btf_type(const struct btf *btf, __u32 id,
const struct btf_type *t)
{
json_writer_t *w = json_wtr;
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
int kind = btf_kind(t);
if (json_output) {
jsonw_start_object(w);
jsonw_uint_field(w, "id", id);
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]);
jsonw_string_field(w, "name", btf_str(btf, t->name_off));
} else {
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)],
btf_str(btf, t->name_off));
}
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
switch (kind) {
case BTF_KIND_INT: {
__u32 v = *(__u32 *)(t + 1);
const char *enc;
enc = btf_int_enc_str(BTF_INT_ENCODING(v));
if (json_output) {
jsonw_uint_field(w, "size", t->size);
jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v));
jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v));
jsonw_string_field(w, "encoding", enc);
} else {
printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s",
t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v),
enc);
}
break;
}
case BTF_KIND_PTR:
case BTF_KIND_CONST:
case BTF_KIND_VOLATILE:
case BTF_KIND_RESTRICT:
case BTF_KIND_TYPEDEF:
case BTF_KIND_TYPE_TAG:
if (json_output)
jsonw_uint_field(w, "type_id", t->type);
else
printf(" type_id=%u", t->type);
break;
case BTF_KIND_ARRAY: {
const struct btf_array *arr = (const void *)(t + 1);
if (json_output) {
jsonw_uint_field(w, "type_id", arr->type);
jsonw_uint_field(w, "index_type_id", arr->index_type);
jsonw_uint_field(w, "nr_elems", arr->nelems);
} else {
printf(" type_id=%u index_type_id=%u nr_elems=%u",
arr->type, arr->index_type, arr->nelems);
}
break;
}
case BTF_KIND_STRUCT:
case BTF_KIND_UNION: {
const struct btf_member *m = (const void *)(t + 1);
__u16 vlen = BTF_INFO_VLEN(t->info);
int i;
if (json_output) {
jsonw_uint_field(w, "size", t->size);
jsonw_uint_field(w, "vlen", vlen);
jsonw_name(w, "members");
jsonw_start_array(w);
} else {
printf(" size=%u vlen=%u", t->size, vlen);
}
for (i = 0; i < vlen; i++, m++) {
const char *name = btf_str(btf, m->name_off);
__u32 bit_off, bit_sz;
if (BTF_INFO_KFLAG(t->info)) {
bit_off = BTF_MEMBER_BIT_OFFSET(m->offset);
bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset);
} else {
bit_off = m->offset;
bit_sz = 0;
}
if (json_output) {
jsonw_start_object(w);
jsonw_string_field(w, "name", name);
jsonw_uint_field(w, "type_id", m->type);
jsonw_uint_field(w, "bits_offset", bit_off);
if (bit_sz) {
jsonw_uint_field(w, "bitfield_size",
bit_sz);
}
jsonw_end_object(w);
} else {
printf("\n\t'%s' type_id=%u bits_offset=%u",
name, m->type, bit_off);
if (bit_sz)
printf(" bitfield_size=%u", bit_sz);
}
}
if (json_output)
jsonw_end_array(w);
break;
}
case BTF_KIND_ENUM: {
const struct btf_enum *v = (const void *)(t + 1);
__u16 vlen = BTF_INFO_VLEN(t->info);
const char *encoding;
int i;
encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
if (json_output) {
jsonw_string_field(w, "encoding", encoding);
jsonw_uint_field(w, "size", t->size);
jsonw_uint_field(w, "vlen", vlen);
jsonw_name(w, "values");
jsonw_start_array(w);
} else {
printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
}
for (i = 0; i < vlen; i++, v++) {
const char *name = btf_str(btf, v->name_off);
if (json_output) {
jsonw_start_object(w);
jsonw_string_field(w, "name", name);
if (btf_kflag(t))
jsonw_int_field(w, "val", v->val);
else
jsonw_uint_field(w, "val", v->val);
jsonw_end_object(w);
} else {
if (btf_kflag(t))
printf("\n\t'%s' val=%d", name, v->val);
else
printf("\n\t'%s' val=%u", name, v->val);
}
}
if (json_output)
jsonw_end_array(w);
break;
}
case BTF_KIND_ENUM64: {
const struct btf_enum64 *v = btf_enum64(t);
__u16 vlen = btf_vlen(t);
const char *encoding;
int i;
encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
if (json_output) {
jsonw_string_field(w, "encoding", encoding);
jsonw_uint_field(w, "size", t->size);
jsonw_uint_field(w, "vlen", vlen);
jsonw_name(w, "values");
jsonw_start_array(w);
} else {
printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
}
for (i = 0; i < vlen; i++, v++) {
const char *name = btf_str(btf, v->name_off);
__u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
if (json_output) {
jsonw_start_object(w);
jsonw_string_field(w, "name", name);
if (btf_kflag(t))
jsonw_int_field(w, "val", val);
else
jsonw_uint_field(w, "val", val);
jsonw_end_object(w);
} else {
if (btf_kflag(t))
printf("\n\t'%s' val=%lldLL", name,
(unsigned long long)val);
else
printf("\n\t'%s' val=%lluULL", name,
(unsigned long long)val);
}
}
if (json_output)
jsonw_end_array(w);
break;
}
case BTF_KIND_FWD: {
const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union"
: "struct";
if (json_output)
jsonw_string_field(w, "fwd_kind", fwd_kind);
else
printf(" fwd_kind=%s", fwd_kind);
break;
}
case BTF_KIND_FUNC: {
const char *linkage = btf_func_linkage_str(t);
if (json_output) {
jsonw_uint_field(w, "type_id", t->type);
jsonw_string_field(w, "linkage", linkage);
} else {
printf(" type_id=%u linkage=%s", t->type, linkage);
}
break;
}
case BTF_KIND_FUNC_PROTO: {
const struct btf_param *p = (const void *)(t + 1);
__u16 vlen = BTF_INFO_VLEN(t->info);
int i;
if (json_output) {
jsonw_uint_field(w, "ret_type_id", t->type);
jsonw_uint_field(w, "vlen", vlen);
jsonw_name(w, "params");
jsonw_start_array(w);
} else {
printf(" ret_type_id=%u vlen=%u", t->type, vlen);
}
for (i = 0; i < vlen; i++, p++) {
const char *name = btf_str(btf, p->name_off);
if (json_output) {
jsonw_start_object(w);
jsonw_string_field(w, "name", name);
jsonw_uint_field(w, "type_id", p->type);
jsonw_end_object(w);
} else {
printf("\n\t'%s' type_id=%u", name, p->type);
}
}
if (json_output)
jsonw_end_array(w);
break;
}
case BTF_KIND_VAR: {
const struct btf_var *v = (const void *)(t + 1);
const char *linkage;
linkage = btf_var_linkage_str(v->linkage);
if (json_output) {
jsonw_uint_field(w, "type_id", t->type);
jsonw_string_field(w, "linkage", linkage);
} else {
printf(" type_id=%u, linkage=%s", t->type, linkage);
}
break;
}
case BTF_KIND_DATASEC: {
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
const struct btf_var_secinfo *v = (const void *)(t + 1);
const struct btf_type *vt;
__u16 vlen = BTF_INFO_VLEN(t->info);
int i;
if (json_output) {
jsonw_uint_field(w, "size", t->size);
jsonw_uint_field(w, "vlen", vlen);
jsonw_name(w, "vars");
jsonw_start_array(w);
} else {
printf(" size=%u vlen=%u", t->size, vlen);
}
for (i = 0; i < vlen; i++, v++) {
if (json_output) {
jsonw_start_object(w);
jsonw_uint_field(w, "type_id", v->type);
jsonw_uint_field(w, "offset", v->offset);
jsonw_uint_field(w, "size", v->size);
jsonw_end_object(w);
} else {
printf("\n\ttype_id=%u offset=%u size=%u",
v->type, v->offset, v->size);
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
if (v->type < btf__type_cnt(btf)) {
bpftool: Dump more info about DATASEC members Dump succinct information for each member of DATASEC: its kinds and name. This is extremely helpful to see at a quick glance what is inside each DATASEC of a given BTF. Without this, one has to jump around BTF data to just find out the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that regard because it doesn't itself contain the name of the member, delegating that to the referenced VAR and FUNC kinds. Other kinds, like STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly identifiable in BTF dump. The new output looks like this: [35] DATASEC '.bss' size=0 vlen=6 type_id=8 offset=0 size=4 (VAR 'input_bss1') type_id=13 offset=0 size=4 (VAR 'input_bss_weak') type_id=16 offset=0 size=4 (VAR 'output_bss1') type_id=17 offset=0 size=4 (VAR 'output_data1') type_id=18 offset=0 size=4 (VAR 'output_rodata1') type_id=20 offset=0 size=8 (VAR 'output_sink1') [36] DATASEC '.data' size=0 vlen=2 type_id=9 offset=0 size=4 (VAR 'input_data1') type_id=14 offset=0 size=4 (VAR 'input_data_weak') [37] DATASEC '.kconfig' size=0 vlen=2 type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION') type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL') [38] DATASEC '.ksyms' size=0 vlen=1 type_id=30 offset=0 size=1 (VAR 'bpf_link_fops') [39] DATASEC '.rodata' size=0 vlen=2 type_id=12 offset=0 size=4 (VAR 'input_rodata1') type_id=15 offset=0 size=4 (VAR 'input_rodata_weak') [40] DATASEC 'license' size=0 vlen=1 type_id=24 offset=0 size=4 (VAR 'LICENSE') Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org
2021-04-23 18:13:32 +00:00
vt = btf__type_by_id(btf, v->type);
printf(" (%s '%s')",
btf_kind_str[btf_kind_safe(btf_kind(vt))],
btf_str(btf, vt->name_off));
}
}
}
if (json_output)
jsonw_end_array(w);
break;
}
case BTF_KIND_FLOAT: {
if (json_output)
jsonw_uint_field(w, "size", t->size);
else
printf(" size=%u", t->size);
break;
}
bpf: Rename BTF_KIND_TAG to BTF_KIND_DECL_TAG Bugzilla: http://bugzilla.redhat.com/2069045 commit 223f903e9c832699f4e5f422281a60756c1c6cfe Author: Yonghong Song <yhs@fb.com> Date: Tue Oct 12 09:48:38 2021 -0700 bpf: Rename BTF_KIND_TAG to BTF_KIND_DECL_TAG Patch set [1] introduced BTF_KIND_TAG to allow tagging declarations for struct/union, struct/union field, var, func and func arguments and these tags will be encoded into dwarf. They are also encoded to btf by llvm for the bpf target. After BTF_KIND_TAG is introduced, we intended to use it for kernel __user attributes. But kernel __user is actually a type attribute. Upstream and internal discussion showed it is not a good idea to mix declaration attribute and type attribute. So we proposed to introduce btf_type_tag as a type attribute and existing btf_tag renamed to btf_decl_tag ([2]). This patch renamed BTF_KIND_TAG to BTF_KIND_DECL_TAG and some other declarations with *_tag to *_decl_tag to make it clear the tag is for declaration. In the future, BTF_KIND_TYPE_TAG might be introduced per [3]. [1] https://lore.kernel.org/bpf/20210914223004.244411-1-yhs@fb.com/ [2] https://reviews.llvm.org/D111588 [3] https://reviews.llvm.org/D111199 Fixes: b5ea834dde6b ("bpf: Support for new btf kind BTF_KIND_TAG") Fixes: 5b84bd10363e ("libbpf: Add support for BTF_KIND_TAG") Fixes: 5c07f2fec003 ("bpftool: Add support for BTF_KIND_TAG") Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20211012164838.3345699-1-yhs@fb.com Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
2022-04-26 09:29:28 +00:00
case BTF_KIND_DECL_TAG: {
const struct btf_decl_tag *tag = (const void *)(t + 1);
if (json_output) {
jsonw_uint_field(w, "type_id", t->type);
jsonw_int_field(w, "component_idx", tag->component_idx);
} else {
printf(" type_id=%u component_idx=%d", t->type, tag->component_idx);
}
break;
}
default:
break;
}
if (json_output)
jsonw_end_object(json_wtr);
else
printf("\n");
return 0;
}
static int dump_btf_raw(const struct btf *btf,
__u32 *root_type_ids, int root_type_cnt)
{
const struct btf_type *t;
int i;
if (json_output) {
jsonw_start_object(json_wtr);
jsonw_name(json_wtr, "types");
jsonw_start_array(json_wtr);
}
if (root_type_cnt) {
for (i = 0; i < root_type_cnt; i++) {
t = btf__type_by_id(btf, root_type_ids[i]);
dump_btf_type(btf, root_type_ids[i], t);
}
} else {
const struct btf *base;
int cnt = btf__type_cnt(btf);
int start_id = 1;
base = btf__base_btf(btf);
if (base)
start_id = btf__type_cnt(base);
for (i = start_id; i < cnt; i++) {
t = btf__type_by_id(btf, i);
dump_btf_type(btf, i, t);
}
}
if (json_output) {
jsonw_end_array(json_wtr);
jsonw_end_object(json_wtr);
}
return 0;
}
static int dump_btf_kfuncs(struct btf_dump *d, const struct btf *btf)
{
LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts);
int cnt = btf__type_cnt(btf);
int i;
printf("\n/* BPF kfuncs */\n");
printf("#ifndef BPF_NO_KFUNC_PROTOTYPES\n");
for (i = 1; i < cnt; i++) {
const struct btf_type *t = btf__type_by_id(btf, i);
const char *name;
int err;
if (!btf_is_decl_tag(t))
continue;
if (btf_decl_tag(t)->component_idx != -1)
continue;
name = btf__name_by_offset(btf, t->name_off);
if (strncmp(name, KFUNC_DECL_TAG, sizeof(KFUNC_DECL_TAG)))
continue;
t = btf__type_by_id(btf, t->type);
if (!btf_is_func(t))
continue;
printf("extern ");
opts.field_name = btf__name_by_offset(btf, t->name_off);
err = btf_dump__emit_type_decl(d, t->type, &opts);
if (err)
return err;
printf(" __weak __ksym;\n");
}
printf("#endif\n\n");
return 0;
}
static void __printf(2, 0) btf_dump_printf(void *ctx,
const char *fmt, va_list args)
{
vfprintf(stdout, fmt, args);
}
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
static int btf_type_rank(const struct btf *btf, __u32 index, bool has_name)
{
const struct btf_type *t = btf__type_by_id(btf, index);
const int kind = btf_kind(t);
const int max_rank = 10;
if (t->name_off)
has_name = true;
switch (kind) {
case BTF_KIND_ENUM:
case BTF_KIND_ENUM64:
return has_name ? 1 : 0;
case BTF_KIND_INT:
case BTF_KIND_FLOAT:
return 2;
case BTF_KIND_STRUCT:
case BTF_KIND_UNION:
return has_name ? 3 : max_rank;
case BTF_KIND_FUNC_PROTO:
return has_name ? 4 : max_rank;
case BTF_KIND_ARRAY:
if (has_name)
return btf_type_rank(btf, btf_array(t)->type, has_name);
return max_rank;
case BTF_KIND_TYPE_TAG:
case BTF_KIND_CONST:
case BTF_KIND_PTR:
case BTF_KIND_VOLATILE:
case BTF_KIND_RESTRICT:
case BTF_KIND_TYPEDEF:
case BTF_KIND_DECL_TAG:
if (has_name)
return btf_type_rank(btf, t->type, has_name);
return max_rank;
default:
return max_rank;
}
}
static const char *btf_type_sort_name(const struct btf *btf, __u32 index, bool from_ref)
{
const struct btf_type *t = btf__type_by_id(btf, index);
switch (btf_kind(t)) {
case BTF_KIND_ENUM:
case BTF_KIND_ENUM64: {
int name_off = t->name_off;
if (!from_ref && !name_off && btf_vlen(t))
name_off = btf_kind(t) == BTF_KIND_ENUM64 ?
btf_enum64(t)->name_off :
btf_enum(t)->name_off;
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
return btf__name_by_offset(btf, name_off);
}
case BTF_KIND_ARRAY:
return btf_type_sort_name(btf, btf_array(t)->type, true);
case BTF_KIND_TYPE_TAG:
case BTF_KIND_CONST:
case BTF_KIND_PTR:
case BTF_KIND_VOLATILE:
case BTF_KIND_RESTRICT:
case BTF_KIND_TYPEDEF:
case BTF_KIND_DECL_TAG:
return btf_type_sort_name(btf, t->type, true);
default:
return btf__name_by_offset(btf, t->name_off);
}
return NULL;
}
static __u64 hasher(__u64 hash, __u64 val)
{
return hash * 31 + val;
}
static __u64 btf_name_hasher(__u64 hash, const struct btf *btf, __u32 name_off)
{
if (!name_off)
return hash;
return hasher(hash, str_hash(btf__name_by_offset(btf, name_off)));
}
static __u64 btf_type_disambig_hash(const struct btf *btf, __u32 id, bool include_members)
{
const struct btf_type *t = btf__type_by_id(btf, id);
int i;
size_t hash = 0;
hash = btf_name_hasher(hash, btf, t->name_off);
switch (btf_kind(t)) {
case BTF_KIND_ENUM:
case BTF_KIND_ENUM64:
for (i = 0; i < btf_vlen(t); i++) {
__u32 name_off = btf_is_enum(t) ?
btf_enum(t)[i].name_off :
btf_enum64(t)[i].name_off;
hash = btf_name_hasher(hash, btf, name_off);
}
break;
case BTF_KIND_STRUCT:
case BTF_KIND_UNION:
if (!include_members)
break;
for (i = 0; i < btf_vlen(t); i++) {
const struct btf_member *m = btf_members(t) + i;
hash = btf_name_hasher(hash, btf, m->name_off);
/* resolve field type's name and hash it as well */
hash = hasher(hash, btf_type_disambig_hash(btf, m->type, false));
}
break;
case BTF_KIND_TYPE_TAG:
case BTF_KIND_CONST:
case BTF_KIND_PTR:
case BTF_KIND_VOLATILE:
case BTF_KIND_RESTRICT:
case BTF_KIND_TYPEDEF:
case BTF_KIND_DECL_TAG:
hash = hasher(hash, btf_type_disambig_hash(btf, t->type, include_members));
break;
case BTF_KIND_ARRAY: {
struct btf_array *arr = btf_array(t);
hash = hasher(hash, arr->nelems);
hash = hasher(hash, btf_type_disambig_hash(btf, arr->type, include_members));
break;
}
default:
break;
}
return hash;
}
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
static int btf_type_compare(const void *left, const void *right)
{
const struct sort_datum *d1 = (const struct sort_datum *)left;
const struct sort_datum *d2 = (const struct sort_datum *)right;
int r;
r = d1->type_rank - d2->type_rank;
r = r ?: strcmp(d1->sort_name, d2->sort_name);
r = r ?: strcmp(d1->own_name, d2->own_name);
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
if (r)
return r;
if (d1->disambig_hash != d2->disambig_hash)
return d1->disambig_hash < d2->disambig_hash ? -1 : 1;
return d1->index - d2->index;
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
}
static struct sort_datum *sort_btf_c(const struct btf *btf)
{
struct sort_datum *datums;
int n;
n = btf__type_cnt(btf);
datums = malloc(sizeof(struct sort_datum) * n);
if (!datums)
return NULL;
for (int i = 0; i < n; ++i) {
struct sort_datum *d = datums + i;
const struct btf_type *t = btf__type_by_id(btf, i);
d->index = i;
d->type_rank = btf_type_rank(btf, i, false);
d->sort_name = btf_type_sort_name(btf, i, false);
d->own_name = btf__name_by_offset(btf, t->name_off);
d->disambig_hash = btf_type_disambig_hash(btf, i, true);
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
}
qsort(datums, n, sizeof(struct sort_datum), btf_type_compare);
return datums;
}
static int dump_btf_c(const struct btf *btf,
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
__u32 *root_type_ids, int root_type_cnt, bool sort_dump)
{
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
struct sort_datum *datums = NULL;
struct btf_dump *d;
int err = 0, i;
d = btf_dump__new(btf, btf_dump_printf, NULL, NULL);
if (!d)
return -errno;
printf("#ifndef __VMLINUX_H__\n");
printf("#define __VMLINUX_H__\n");
printf("\n");
printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n");
printf("#endif\n\n");
printf("#ifndef __ksym\n");
printf("#define __ksym __attribute__((section(\".ksyms\")))\n");
printf("#endif\n\n");
printf("#ifndef __weak\n");
printf("#define __weak __attribute__((weak))\n");
printf("#endif\n\n");
if (root_type_cnt) {
for (i = 0; i < root_type_cnt; i++) {
err = btf_dump__dump_type(d, root_type_ids[i]);
if (err)
goto done;
}
} else {
int cnt = btf__type_cnt(btf);
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
if (sort_dump)
datums = sort_btf_c(btf);
for (i = 1; i < cnt; i++) {
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
int idx = datums ? datums[i].index : i;
err = btf_dump__dump_type(d, idx);
if (err)
goto done;
}
err = dump_btf_kfuncs(d, btf);
if (err)
goto done;
}
printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
printf("#pragma clang attribute pop\n");
printf("#endif\n");
printf("\n");
printf("#endif /* __VMLINUX_H__ */\n");
done:
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
free(datums);
btf_dump__free(d);
return err;
}
static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
static struct btf *get_vmlinux_btf_from_sysfs(void)
{
struct btf *base;
base = btf__parse(sysfs_vmlinux, NULL);
if (!base)
p_err("failed to parse vmlinux BTF at '%s': %d\n",
sysfs_vmlinux, -errno);
return base;
}
#define BTF_NAME_BUFF_LEN 64
static bool btf_is_kernel_module(__u32 btf_id)
{
struct bpf_btf_info btf_info = {};
char btf_name[BTF_NAME_BUFF_LEN];
int btf_fd;
__u32 len;
int err;
btf_fd = bpf_btf_get_fd_by_id(btf_id);
if (btf_fd < 0) {
p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno));
return false;
}
len = sizeof(btf_info);
btf_info.name = ptr_to_u64(btf_name);
btf_info.name_len = sizeof(btf_name);
err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len);
close(btf_fd);
if (err) {
p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno));
return false;
}
return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0;
}
static int do_dump(int argc, char **argv)
{
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
bool dump_c = false, sort_dump_c = true;
struct btf *btf = NULL, *base = NULL;
__u32 root_type_ids[2];
int root_type_cnt = 0;
__u32 btf_id = -1;
const char *src;
int fd = -1;
int err = 0;
if (!REQ_ARGS(2)) {
usage();
return -1;
}
src = GET_ARG();
if (is_prefix(src, "map")) {
struct bpf_map_info info = {};
__u32 len = sizeof(info);
if (!REQ_ARGS(2)) {
usage();
return -1;
}
fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
if (fd < 0)
return -1;
btf_id = info.btf_id;
if (argc && is_prefix(*argv, "key")) {
root_type_ids[root_type_cnt++] = info.btf_key_type_id;
NEXT_ARG();
} else if (argc && is_prefix(*argv, "value")) {
root_type_ids[root_type_cnt++] = info.btf_value_type_id;
NEXT_ARG();
} else if (argc && is_prefix(*argv, "all")) {
NEXT_ARG();
} else if (argc && is_prefix(*argv, "kv")) {
root_type_ids[root_type_cnt++] = info.btf_key_type_id;
root_type_ids[root_type_cnt++] = info.btf_value_type_id;
NEXT_ARG();
} else {
root_type_ids[root_type_cnt++] = info.btf_key_type_id;
root_type_ids[root_type_cnt++] = info.btf_value_type_id;
}
} else if (is_prefix(src, "prog")) {
struct bpf_prog_info info = {};
__u32 len = sizeof(info);
if (!REQ_ARGS(2)) {
usage();
return -1;
}
fd = prog_parse_fd(&argc, &argv);
if (fd < 0)
return -1;
err = bpf_prog_get_info_by_fd(fd, &info, &len);
if (err) {
p_err("can't get prog info: %s", strerror(errno));
goto done;
}
btf_id = info.btf_id;
} else if (is_prefix(src, "id")) {
char *endptr;
btf_id = strtoul(*argv, &endptr, 0);
if (*endptr) {
p_err("can't parse %s as ID", *argv);
return -1;
}
NEXT_ARG();
} else if (is_prefix(src, "file")) {
const char sysfs_prefix[] = "/sys/kernel/btf/";
if (!base_btf &&
strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
strcmp(*argv, sysfs_vmlinux) != 0)
base = get_vmlinux_btf_from_sysfs();
btf = btf__parse_split(*argv, base ?: base_btf);
if (!btf) {
err = -errno;
p_err("failed to load BTF from %s: %s",
*argv, strerror(errno));
goto done;
}
NEXT_ARG();
} else {
err = -1;
p_err("unrecognized BTF source specifier: '%s'", src);
goto done;
}
while (argc) {
if (is_prefix(*argv, "format")) {
NEXT_ARG();
if (argc < 1) {
p_err("expecting value for 'format' option\n");
err = -EINVAL;
goto done;
}
if (strcmp(*argv, "c") == 0) {
dump_c = true;
} else if (strcmp(*argv, "raw") == 0) {
dump_c = false;
} else {
p_err("unrecognized format specifier: '%s', possible values: raw, c",
*argv);
err = -EINVAL;
goto done;
}
NEXT_ARG();
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
} else if (is_prefix(*argv, "unsorted")) {
sort_dump_c = false;
NEXT_ARG();
} else {
p_err("unrecognized option: '%s'", *argv);
err = -EINVAL;
goto done;
}
}
if (!btf) {
if (!base_btf && btf_is_kernel_module(btf_id)) {
p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)",
sysfs_vmlinux);
base_btf = get_vmlinux_btf_from_sysfs();
}
tools: bpftool: Support dumping split BTF by id Bugzilla: http://bugzilla.redhat.com/2041365 commit 211ab78f7658b50ea10c4569be63ca5009fd39b4 Author: Quentin Monnet <quentin@isovalent.com> Date: Thu Jul 29 17:20:28 2021 +0100 tools: bpftool: Support dumping split BTF by id Split BTF objects are typically BTF objects for kernel modules, which are incrementally built on top of kernel BTF instead of redefining all kernel symbols they need. We can use bpftool with its -B command-line option to dump split BTF objects. It works well when the handle provided for the BTF object to dump is a "path" to the BTF object, typically under /sys/kernel/btf, because bpftool internally calls btf__parse_split() which can take a "base_btf" pointer and resolve the BTF reconstruction (although in that case, the "-B" option is unnecessary because bpftool performs autodetection). However, it did not work so far when passing the BTF object through its id, because bpftool would call btf__get_from_id() which did not provide a way to pass a "base_btf" pointer. In other words, the following works: # bpftool btf dump file /sys/kernel/btf/i2c_smbus -B /sys/kernel/btf/vmlinux But this was not possible: # bpftool btf dump id 6 -B /sys/kernel/btf/vmlinux The libbpf API has recently changed, and btf__get_from_id() has been deprecated in favour of btf__load_from_kernel_by_id() and its version with support for split BTF, btf__load_from_kernel_by_id_split(). Let's update bpftool to make it able to dump the BTF object in the second case as well. Signed-off-by: Quentin Monnet <quentin@isovalent.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20210729162028.29512-9-quentin@isovalent.com Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2022-01-17 14:00:22 +00:00
btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
if (!btf) {
err = -errno;
p_err("get btf by id (%u): %s", btf_id, strerror(errno));
goto done;
}
}
if (dump_c) {
if (json_output) {
p_err("JSON output for C-syntax dump is not supported");
err = -ENOTSUP;
goto done;
}
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
err = dump_btf_c(btf, root_type_ids, root_type_cnt, sort_dump_c);
} else {
err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
}
done:
close(fd);
btf__free(btf);
btf__free(base);
return err;
}
static int btf_parse_fd(int *argc, char ***argv)
{
unsigned int id;
char *endptr;
int fd;
if (!is_prefix(*argv[0], "id")) {
p_err("expected 'id', got: '%s'?", **argv);
return -1;
}
NEXT_ARGP();
id = strtoul(**argv, &endptr, 0);
if (*endptr) {
p_err("can't parse %s as ID", **argv);
return -1;
}
NEXT_ARGP();
fd = bpf_btf_get_fd_by_id(id);
if (fd < 0)
p_err("can't get BTF object by id (%u): %s",
id, strerror(errno));
return fd;
}
static int
build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
void *info, __u32 *len)
{
static const char * const names[] = {
[BPF_OBJ_UNKNOWN] = "unknown",
[BPF_OBJ_PROG] = "prog",
[BPF_OBJ_MAP] = "map",
};
__u32 btf_id, id = 0;
int err;
int fd;
while (true) {
switch (type) {
case BPF_OBJ_PROG:
err = bpf_prog_get_next_id(id, &id);
break;
case BPF_OBJ_MAP:
err = bpf_map_get_next_id(id, &id);
break;
default:
err = -1;
p_err("unexpected object type: %d", type);
goto err_free;
}
if (err) {
if (errno == ENOENT) {
err = 0;
break;
}
p_err("can't get next %s: %s%s", names[type],
strerror(errno),
errno == EINVAL ? " -- kernel too old?" : "");
goto err_free;
}
switch (type) {
case BPF_OBJ_PROG:
fd = bpf_prog_get_fd_by_id(id);
break;
case BPF_OBJ_MAP:
fd = bpf_map_get_fd_by_id(id);
break;
default:
err = -1;
p_err("unexpected object type: %d", type);
goto err_free;
}
if (fd < 0) {
if (errno == ENOENT)
continue;
p_err("can't get %s by id (%u): %s", names[type], id,
strerror(errno));
err = -1;
goto err_free;
}
memset(info, 0, *len);
if (type == BPF_OBJ_PROG)
err = bpf_prog_get_info_by_fd(fd, info, len);
else
err = bpf_map_get_info_by_fd(fd, info, len);
close(fd);
if (err) {
p_err("can't get %s info: %s", names[type],
strerror(errno));
goto err_free;
}
switch (type) {
case BPF_OBJ_PROG:
btf_id = ((struct bpf_prog_info *)info)->btf_id;
break;
case BPF_OBJ_MAP:
btf_id = ((struct bpf_map_info *)info)->btf_id;
break;
default:
err = -1;
p_err("unexpected object type: %d", type);
goto err_free;
}
if (!btf_id)
continue;
libbpf: Hashmap interface update to allow both long and void* keys/values Bugzilla: https://bugzilla.redhat.com/2177177 Conflicts: Some minor changes due to missing commits 09b73fe9e3de ("perf smt: Compute SMT from topology") and f0c4b97a2927 ("perf test: Add basic core_wide expression test"). commit c302378bc157f6a73b6cae4ca67f5f6aa931dcec Author: Eduard Zingerman <eddyz87@gmail.com> Date: Wed Nov 9 16:26:09 2022 +0200 libbpf: Hashmap interface update to allow both long and void* keys/values An update for libbpf's hashmap interface from void* -> void* to a polymorphic one, allowing both long and void* keys and values. This simplifies many use cases in libbpf as hashmaps there are mostly integer to integer. Perf copies hashmap implementation from libbpf and has to be updated as well. Changes to libbpf, selftests/bpf and perf are packed as a single commit to avoid compilation issues with any future bisect. Polymorphic interface is acheived by hiding hashmap interface functions behind auxiliary macros that take care of necessary type casts, for example: #define hashmap_cast_ptr(p) \ ({ \ _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),\ #p " pointee should be a long-sized integer or a pointer"); \ (long *)(p); \ }) bool hashmap_find(const struct hashmap *map, long key, long *value); #define hashmap__find(map, key, value) \ hashmap_find((map), (long)(key), hashmap_cast_ptr(value)) - hashmap__find macro casts key and value parameters to long and long* respectively - hashmap_cast_ptr ensures that value pointer points to a memory of appropriate size. This hack was suggested by Andrii Nakryiko in [1]. This is a follow up for [2]. [1] https://lore.kernel.org/bpf/CAEf4BzZ8KFneEJxFAaNCCFPGqp20hSpS2aCj76uRk3-qZUH5xg@mail.gmail.com/ [2] https://lore.kernel.org/bpf/af1facf9-7bc8-8a3d-0db4-7b3f333589a2@meta.com/T/#m65b28f1d6d969fcd318b556db6a3ad499a42607d Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20221109142611.879983-2-eddyz87@gmail.com Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-15 09:59:40 +00:00
err = hashmap__append(tab, btf_id, id);
if (err) {
p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
btf_id, id, strerror(-err));
goto err_free;
}
}
return 0;
err_free:
hashmap__free(tab);
return err;
}
static int
build_btf_tables(struct hashmap *btf_prog_table,
struct hashmap *btf_map_table)
{
struct bpf_prog_info prog_info;
__u32 prog_len = sizeof(prog_info);
struct bpf_map_info map_info;
__u32 map_len = sizeof(map_info);
int err = 0;
err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info,
&prog_len);
if (err)
return err;
err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
&map_len);
if (err) {
hashmap__free(btf_prog_table);
return err;
}
return 0;
}
static void
show_btf_plain(struct bpf_btf_info *info, int fd,
struct hashmap *btf_prog_table,
struct hashmap *btf_map_table)
{
struct hashmap_entry *entry;
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
const char *name = u64_to_ptr(info->name);
int n;
printf("%u: ", info->id);
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
if (info->kernel_btf)
printf("name [%s] ", name);
else if (name && name[0])
printf("name %s ", name);
else
printf("name <anon> ");
printf("size %uB", info->btf_size);
n = 0;
libbpf: Hashmap interface update to allow both long and void* keys/values Bugzilla: https://bugzilla.redhat.com/2177177 Conflicts: Some minor changes due to missing commits 09b73fe9e3de ("perf smt: Compute SMT from topology") and f0c4b97a2927 ("perf test: Add basic core_wide expression test"). commit c302378bc157f6a73b6cae4ca67f5f6aa931dcec Author: Eduard Zingerman <eddyz87@gmail.com> Date: Wed Nov 9 16:26:09 2022 +0200 libbpf: Hashmap interface update to allow both long and void* keys/values An update for libbpf's hashmap interface from void* -> void* to a polymorphic one, allowing both long and void* keys and values. This simplifies many use cases in libbpf as hashmaps there are mostly integer to integer. Perf copies hashmap implementation from libbpf and has to be updated as well. Changes to libbpf, selftests/bpf and perf are packed as a single commit to avoid compilation issues with any future bisect. Polymorphic interface is acheived by hiding hashmap interface functions behind auxiliary macros that take care of necessary type casts, for example: #define hashmap_cast_ptr(p) \ ({ \ _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),\ #p " pointee should be a long-sized integer or a pointer"); \ (long *)(p); \ }) bool hashmap_find(const struct hashmap *map, long key, long *value); #define hashmap__find(map, key, value) \ hashmap_find((map), (long)(key), hashmap_cast_ptr(value)) - hashmap__find macro casts key and value parameters to long and long* respectively - hashmap_cast_ptr ensures that value pointer points to a memory of appropriate size. This hack was suggested by Andrii Nakryiko in [1]. This is a follow up for [2]. [1] https://lore.kernel.org/bpf/CAEf4BzZ8KFneEJxFAaNCCFPGqp20hSpS2aCj76uRk3-qZUH5xg@mail.gmail.com/ [2] https://lore.kernel.org/bpf/af1facf9-7bc8-8a3d-0db4-7b3f333589a2@meta.com/T/#m65b28f1d6d969fcd318b556db6a3ad499a42607d Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20221109142611.879983-2-eddyz87@gmail.com Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-15 09:59:40 +00:00
hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
printf("%s%lu", n++ == 0 ? " prog_ids " : ",", entry->value);
}
n = 0;
libbpf: Hashmap interface update to allow both long and void* keys/values Bugzilla: https://bugzilla.redhat.com/2177177 Conflicts: Some minor changes due to missing commits 09b73fe9e3de ("perf smt: Compute SMT from topology") and f0c4b97a2927 ("perf test: Add basic core_wide expression test"). commit c302378bc157f6a73b6cae4ca67f5f6aa931dcec Author: Eduard Zingerman <eddyz87@gmail.com> Date: Wed Nov 9 16:26:09 2022 +0200 libbpf: Hashmap interface update to allow both long and void* keys/values An update for libbpf's hashmap interface from void* -> void* to a polymorphic one, allowing both long and void* keys and values. This simplifies many use cases in libbpf as hashmaps there are mostly integer to integer. Perf copies hashmap implementation from libbpf and has to be updated as well. Changes to libbpf, selftests/bpf and perf are packed as a single commit to avoid compilation issues with any future bisect. Polymorphic interface is acheived by hiding hashmap interface functions behind auxiliary macros that take care of necessary type casts, for example: #define hashmap_cast_ptr(p) \ ({ \ _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),\ #p " pointee should be a long-sized integer or a pointer"); \ (long *)(p); \ }) bool hashmap_find(const struct hashmap *map, long key, long *value); #define hashmap__find(map, key, value) \ hashmap_find((map), (long)(key), hashmap_cast_ptr(value)) - hashmap__find macro casts key and value parameters to long and long* respectively - hashmap_cast_ptr ensures that value pointer points to a memory of appropriate size. This hack was suggested by Andrii Nakryiko in [1]. This is a follow up for [2]. [1] https://lore.kernel.org/bpf/CAEf4BzZ8KFneEJxFAaNCCFPGqp20hSpS2aCj76uRk3-qZUH5xg@mail.gmail.com/ [2] https://lore.kernel.org/bpf/af1facf9-7bc8-8a3d-0db4-7b3f333589a2@meta.com/T/#m65b28f1d6d969fcd318b556db6a3ad499a42607d Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20221109142611.879983-2-eddyz87@gmail.com Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-15 09:59:40 +00:00
hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
printf("%s%lu", n++ == 0 ? " map_ids " : ",", entry->value);
}
bpftool: Switch to libbpf's hashmap for PIDs/names references Bugzilla: http://bugzilla.redhat.com/2069045 commit d6699f8e0f834b40db35466f704705ae757be11a Author: Quentin Monnet <quentin@isovalent.com> Date: Sat Oct 23 21:51:54 2021 +0100 bpftool: Switch to libbpf's hashmap for PIDs/names references In order to show PIDs and names for processes holding references to BPF programs, maps, links, or BTF objects, bpftool creates hash maps to store all relevant information. This commit is part of a set that transitions from the kernel's hash map implementation to the one coming with libbpf. The motivation is to make bpftool less dependent of kernel headers, to ease the path to a potential out-of-tree mirror, like libbpf has. This is the third and final step of the transition, in which we convert the hash maps used for storing the information about the processes holding references to BPF objects (programs, maps, links, BTF), and at last we drop the inclusion of tools/include/linux/hashtable.h. Note: Checkpatch complains about the use of __weak declarations, and the missing empty lines after the bunch of empty function declarations when compiling without the BPF skeletons (none of these were introduced in this patch). We want to keep things as they are, and the reports should be safe to ignore. Signed-off-by: Quentin Monnet <quentin@isovalent.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20211023205154.6710-6-quentin@isovalent.com Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
2022-04-26 09:29:30 +00:00
emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
printf("\n");
}
static void
show_btf_json(struct bpf_btf_info *info, int fd,
struct hashmap *btf_prog_table,
struct hashmap *btf_map_table)
{
struct hashmap_entry *entry;
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
const char *name = u64_to_ptr(info->name);
jsonw_start_object(json_wtr); /* btf object */
jsonw_uint_field(json_wtr, "id", info->id);
jsonw_uint_field(json_wtr, "size", info->btf_size);
jsonw_name(json_wtr, "prog_ids");
jsonw_start_array(json_wtr); /* prog_ids */
libbpf: Hashmap interface update to allow both long and void* keys/values Bugzilla: https://bugzilla.redhat.com/2177177 Conflicts: Some minor changes due to missing commits 09b73fe9e3de ("perf smt: Compute SMT from topology") and f0c4b97a2927 ("perf test: Add basic core_wide expression test"). commit c302378bc157f6a73b6cae4ca67f5f6aa931dcec Author: Eduard Zingerman <eddyz87@gmail.com> Date: Wed Nov 9 16:26:09 2022 +0200 libbpf: Hashmap interface update to allow both long and void* keys/values An update for libbpf's hashmap interface from void* -> void* to a polymorphic one, allowing both long and void* keys and values. This simplifies many use cases in libbpf as hashmaps there are mostly integer to integer. Perf copies hashmap implementation from libbpf and has to be updated as well. Changes to libbpf, selftests/bpf and perf are packed as a single commit to avoid compilation issues with any future bisect. Polymorphic interface is acheived by hiding hashmap interface functions behind auxiliary macros that take care of necessary type casts, for example: #define hashmap_cast_ptr(p) \ ({ \ _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),\ #p " pointee should be a long-sized integer or a pointer"); \ (long *)(p); \ }) bool hashmap_find(const struct hashmap *map, long key, long *value); #define hashmap__find(map, key, value) \ hashmap_find((map), (long)(key), hashmap_cast_ptr(value)) - hashmap__find macro casts key and value parameters to long and long* respectively - hashmap_cast_ptr ensures that value pointer points to a memory of appropriate size. This hack was suggested by Andrii Nakryiko in [1]. This is a follow up for [2]. [1] https://lore.kernel.org/bpf/CAEf4BzZ8KFneEJxFAaNCCFPGqp20hSpS2aCj76uRk3-qZUH5xg@mail.gmail.com/ [2] https://lore.kernel.org/bpf/af1facf9-7bc8-8a3d-0db4-7b3f333589a2@meta.com/T/#m65b28f1d6d969fcd318b556db6a3ad499a42607d Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20221109142611.879983-2-eddyz87@gmail.com Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-15 09:59:40 +00:00
hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
jsonw_uint(json_wtr, entry->value);
}
jsonw_end_array(json_wtr); /* prog_ids */
jsonw_name(json_wtr, "map_ids");
jsonw_start_array(json_wtr); /* map_ids */
libbpf: Hashmap interface update to allow both long and void* keys/values Bugzilla: https://bugzilla.redhat.com/2177177 Conflicts: Some minor changes due to missing commits 09b73fe9e3de ("perf smt: Compute SMT from topology") and f0c4b97a2927 ("perf test: Add basic core_wide expression test"). commit c302378bc157f6a73b6cae4ca67f5f6aa931dcec Author: Eduard Zingerman <eddyz87@gmail.com> Date: Wed Nov 9 16:26:09 2022 +0200 libbpf: Hashmap interface update to allow both long and void* keys/values An update for libbpf's hashmap interface from void* -> void* to a polymorphic one, allowing both long and void* keys and values. This simplifies many use cases in libbpf as hashmaps there are mostly integer to integer. Perf copies hashmap implementation from libbpf and has to be updated as well. Changes to libbpf, selftests/bpf and perf are packed as a single commit to avoid compilation issues with any future bisect. Polymorphic interface is acheived by hiding hashmap interface functions behind auxiliary macros that take care of necessary type casts, for example: #define hashmap_cast_ptr(p) \ ({ \ _Static_assert((p) == NULL || sizeof(*(p)) == sizeof(long),\ #p " pointee should be a long-sized integer or a pointer"); \ (long *)(p); \ }) bool hashmap_find(const struct hashmap *map, long key, long *value); #define hashmap__find(map, key, value) \ hashmap_find((map), (long)(key), hashmap_cast_ptr(value)) - hashmap__find macro casts key and value parameters to long and long* respectively - hashmap_cast_ptr ensures that value pointer points to a memory of appropriate size. This hack was suggested by Andrii Nakryiko in [1]. This is a follow up for [2]. [1] https://lore.kernel.org/bpf/CAEf4BzZ8KFneEJxFAaNCCFPGqp20hSpS2aCj76uRk3-qZUH5xg@mail.gmail.com/ [2] https://lore.kernel.org/bpf/af1facf9-7bc8-8a3d-0db4-7b3f333589a2@meta.com/T/#m65b28f1d6d969fcd318b556db6a3ad499a42607d Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20221109142611.879983-2-eddyz87@gmail.com Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
2023-03-15 09:59:40 +00:00
hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
jsonw_uint(json_wtr, entry->value);
}
jsonw_end_array(json_wtr); /* map_ids */
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs Add bpf_iter-based way to find all the processes that hold open FDs against BPF object (map, prog, link, btf). bpftool always attempts to discover this, but will silently give up if kernel doesn't yet support bpf_iter BPF programs. Process name and PID are emitted for each process (task group). Sample output for each of 4 BPF objects: $ sudo ./bpftool prog show 2694: cgroup_device tag 8c42dee26e8cd4c2 gpl loaded_at 2020-06-16T15:34:32-0700 uid 0 xlated 648B jited 409B memlock 4096B pids systemd(1) 2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl loaded_at 2020-06-16T18:06:54-0700 uid 0 xlated 48B jited 59B memlock 4096B map_ids 2436 btf_id 1202 pids test_progs(2238417), test_progs(2238445) $ sudo ./bpftool map show 2436: array name test_cgr.bss flags 0x400 key 4B value 8B max_entries 1 memlock 8192B btf_id 1202 pids test_progs(2238417), test_progs(2238445) 2445: array name pid_iter.rodata flags 0x480 key 4B value 4B max_entries 1 memlock 8192B btf_id 1214 frozen pids bpftool(2239612) $ sudo ./bpftool link show 61: cgroup prog 2908 cgroup_id 375301 attach_type egress pids test_progs(2238417), test_progs(2238445) 62: cgroup prog 2908 cgroup_id 375344 attach_type egress pids test_progs(2238417), test_progs(2238445) $ sudo ./bpftool btf show 1202: size 1527B prog_ids 2908,2907 map_ids 2436 pids test_progs(2238417), test_progs(2238445) 1242: size 34684B pids bpftool(2258892) Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Quentin Monnet <quentin@isovalent.com> Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-19 23:17:02 +00:00
bpftool: Switch to libbpf's hashmap for PIDs/names references Bugzilla: http://bugzilla.redhat.com/2069045 commit d6699f8e0f834b40db35466f704705ae757be11a Author: Quentin Monnet <quentin@isovalent.com> Date: Sat Oct 23 21:51:54 2021 +0100 bpftool: Switch to libbpf's hashmap for PIDs/names references In order to show PIDs and names for processes holding references to BPF programs, maps, links, or BTF objects, bpftool creates hash maps to store all relevant information. This commit is part of a set that transitions from the kernel's hash map implementation to the one coming with libbpf. The motivation is to make bpftool less dependent of kernel headers, to ease the path to a potential out-of-tree mirror, like libbpf has. This is the third and final step of the transition, in which we convert the hash maps used for storing the information about the processes holding references to BPF objects (programs, maps, links, BTF), and at last we drop the inclusion of tools/include/linux/hashtable.h. Note: Checkpatch complains about the use of __weak declarations, and the missing empty lines after the bunch of empty function declarations when compiling without the BPF skeletons (none of these were introduced in this patch). We want to keep things as they are, and the reports should be safe to ignore. Signed-off-by: Quentin Monnet <quentin@isovalent.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20211023205154.6710-6-quentin@isovalent.com Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
2022-04-26 09:29:30 +00:00
emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs Add bpf_iter-based way to find all the processes that hold open FDs against BPF object (map, prog, link, btf). bpftool always attempts to discover this, but will silently give up if kernel doesn't yet support bpf_iter BPF programs. Process name and PID are emitted for each process (task group). Sample output for each of 4 BPF objects: $ sudo ./bpftool prog show 2694: cgroup_device tag 8c42dee26e8cd4c2 gpl loaded_at 2020-06-16T15:34:32-0700 uid 0 xlated 648B jited 409B memlock 4096B pids systemd(1) 2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl loaded_at 2020-06-16T18:06:54-0700 uid 0 xlated 48B jited 59B memlock 4096B map_ids 2436 btf_id 1202 pids test_progs(2238417), test_progs(2238445) $ sudo ./bpftool map show 2436: array name test_cgr.bss flags 0x400 key 4B value 8B max_entries 1 memlock 8192B btf_id 1202 pids test_progs(2238417), test_progs(2238445) 2445: array name pid_iter.rodata flags 0x480 key 4B value 4B max_entries 1 memlock 8192B btf_id 1214 frozen pids bpftool(2239612) $ sudo ./bpftool link show 61: cgroup prog 2908 cgroup_id 375301 attach_type egress pids test_progs(2238417), test_progs(2238445) 62: cgroup prog 2908 cgroup_id 375344 attach_type egress pids test_progs(2238417), test_progs(2238445) $ sudo ./bpftool btf show 1202: size 1527B prog_ids 2908,2907 map_ids 2436 pids test_progs(2238417), test_progs(2238445) 1242: size 34684B pids bpftool(2258892) Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Quentin Monnet <quentin@isovalent.com> Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-19 23:17:02 +00:00
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
if (name && name[0])
jsonw_string_field(json_wtr, "name", name);
jsonw_end_object(json_wtr); /* btf object */
}
static int
show_btf(int fd, struct hashmap *btf_prog_table,
struct hashmap *btf_map_table)
{
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
struct bpf_btf_info info;
__u32 len = sizeof(info);
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
char name[64];
int err;
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
memset(&info, 0, sizeof(info));
err = bpf_btf_get_info_by_fd(fd, &info, &len);
if (err) {
p_err("can't get BTF object info: %s", strerror(errno));
return -1;
}
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
/* if kernel support emitting BTF object name, pass name pointer */
if (info.name_len) {
memset(&info, 0, sizeof(info));
info.name_len = sizeof(name);
info.name = ptr_to_u64(name);
len = sizeof(info);
err = bpf_btf_get_info_by_fd(fd, &info, &len);
tools/bpftool: Add support for in-kernel and named BTF in `btf show` Display vmlinux BTF name and kernel module names when listing available BTFs on the system. In human-readable output mode, module BTFs are reported with "name [module-name]", while vmlinux BTF will be reported as "name [vmlinux]". Square brackets are added by bpftool and follow kernel convention when displaying modules in human-readable text outputs. [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s 1: name [vmlinux] size 4082281B 6: size 2365B prog_ids 8,6 map_ids 3 7: name [button] size 46895B 8: name [pcspkr] size 42328B 9: name [serio_raw] size 39375B 10: name [floppy] size 57185B 11: name [i2c_core] size 76186B 12: name [crc32c_intel] size 16036B 13: name [i2c_piix4] size 50497B 14: name [irqbypass] size 14124B 15: name [kvm] size 197985B 16: name [kvm_intel] size 123564B 17: name [cryptd] size 42466B 18: name [crypto_simd] size 17187B 19: name [glue_helper] size 39205B 20: name [aesni_intel] size 41034B 25: size 36150B pids bpftool(2519) In JSON mode, two fields (boolean "kernel" and string "name") are reported for each BTF object. vmlinux BTF is reported with name "vmlinux" (kernel itself returns and empty name for vmlinux BTF). [vmuser@archvm bpf]$ sudo ../../../bpf/bpftool/bpftool btf s -jp [{ "id": 1, "size": 4082281, "prog_ids": [], "map_ids": [], "kernel": true, "name": "vmlinux" },{ "id": 6, "size": 2365, "prog_ids": [8,6 ], "map_ids": [3 ], "kernel": false },{ "id": 7, "size": 46895, "prog_ids": [], "map_ids": [], "kernel": true, "name": "button" },{ ... Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Tested-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/20201110011932.3201430-6-andrii@kernel.org
2020-11-10 01:19:32 +00:00
if (err) {
p_err("can't get BTF object info: %s", strerror(errno));
return -1;
}
}
if (json_output)
show_btf_json(&info, fd, btf_prog_table, btf_map_table);
else
show_btf_plain(&info, fd, btf_prog_table, btf_map_table);
return 0;
}
static int do_show(int argc, char **argv)
{
struct hashmap *btf_prog_table;
struct hashmap *btf_map_table;
int err, fd = -1;
__u32 id = 0;
if (argc == 2) {
fd = btf_parse_fd(&argc, &argv);
if (fd < 0)
return -1;
}
if (argc) {
if (fd >= 0)
close(fd);
return BAD_ARG();
}
btf_prog_table = hashmap__new(hash_fn_for_key_as_id,
equal_fn_for_key_as_id, NULL);
btf_map_table = hashmap__new(hash_fn_for_key_as_id,
equal_fn_for_key_as_id, NULL);
if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) {
hashmap__free(btf_prog_table);
hashmap__free(btf_map_table);
if (fd >= 0)
close(fd);
p_err("failed to create hashmap for object references");
return -1;
}
err = build_btf_tables(btf_prog_table, btf_map_table);
if (err) {
if (fd >= 0)
close(fd);
return err;
}
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs Add bpf_iter-based way to find all the processes that hold open FDs against BPF object (map, prog, link, btf). bpftool always attempts to discover this, but will silently give up if kernel doesn't yet support bpf_iter BPF programs. Process name and PID are emitted for each process (task group). Sample output for each of 4 BPF objects: $ sudo ./bpftool prog show 2694: cgroup_device tag 8c42dee26e8cd4c2 gpl loaded_at 2020-06-16T15:34:32-0700 uid 0 xlated 648B jited 409B memlock 4096B pids systemd(1) 2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl loaded_at 2020-06-16T18:06:54-0700 uid 0 xlated 48B jited 59B memlock 4096B map_ids 2436 btf_id 1202 pids test_progs(2238417), test_progs(2238445) $ sudo ./bpftool map show 2436: array name test_cgr.bss flags 0x400 key 4B value 8B max_entries 1 memlock 8192B btf_id 1202 pids test_progs(2238417), test_progs(2238445) 2445: array name pid_iter.rodata flags 0x480 key 4B value 4B max_entries 1 memlock 8192B btf_id 1214 frozen pids bpftool(2239612) $ sudo ./bpftool link show 61: cgroup prog 2908 cgroup_id 375301 attach_type egress pids test_progs(2238417), test_progs(2238445) 62: cgroup prog 2908 cgroup_id 375344 attach_type egress pids test_progs(2238417), test_progs(2238445) $ sudo ./bpftool btf show 1202: size 1527B prog_ids 2908,2907 map_ids 2436 pids test_progs(2238417), test_progs(2238445) 1242: size 34684B pids bpftool(2258892) Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Quentin Monnet <quentin@isovalent.com> Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-19 23:17:02 +00:00
build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
if (fd >= 0) {
err = show_btf(fd, btf_prog_table, btf_map_table);
close(fd);
goto exit_free;
}
if (json_output)
jsonw_start_array(json_wtr); /* root array */
while (true) {
err = bpf_btf_get_next_id(id, &id);
if (err) {
if (errno == ENOENT) {
err = 0;
break;
}
p_err("can't get next BTF object: %s%s",
strerror(errno),
errno == EINVAL ? " -- kernel too old?" : "");
err = -1;
break;
}
fd = bpf_btf_get_fd_by_id(id);
if (fd < 0) {
if (errno == ENOENT)
continue;
p_err("can't get BTF object by id (%u): %s",
id, strerror(errno));
err = -1;
break;
}
err = show_btf(fd, btf_prog_table, btf_map_table);
close(fd);
if (err)
break;
}
if (json_output)
jsonw_end_array(json_wtr); /* root array */
exit_free:
hashmap__free(btf_prog_table);
hashmap__free(btf_map_table);
bpftool: Switch to libbpf's hashmap for PIDs/names references Bugzilla: http://bugzilla.redhat.com/2069045 commit d6699f8e0f834b40db35466f704705ae757be11a Author: Quentin Monnet <quentin@isovalent.com> Date: Sat Oct 23 21:51:54 2021 +0100 bpftool: Switch to libbpf's hashmap for PIDs/names references In order to show PIDs and names for processes holding references to BPF programs, maps, links, or BTF objects, bpftool creates hash maps to store all relevant information. This commit is part of a set that transitions from the kernel's hash map implementation to the one coming with libbpf. The motivation is to make bpftool less dependent of kernel headers, to ease the path to a potential out-of-tree mirror, like libbpf has. This is the third and final step of the transition, in which we convert the hash maps used for storing the information about the processes holding references to BPF objects (programs, maps, links, BTF), and at last we drop the inclusion of tools/include/linux/hashtable.h. Note: Checkpatch complains about the use of __weak declarations, and the missing empty lines after the bunch of empty function declarations when compiling without the BPF skeletons (none of these were introduced in this patch). We want to keep things as they are, and the reports should be safe to ignore. Signed-off-by: Quentin Monnet <quentin@isovalent.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20211023205154.6710-6-quentin@isovalent.com Signed-off-by: Yauheni Kaliuta <ykaliuta@redhat.com>
2022-04-26 09:29:30 +00:00
delete_obj_refs_table(refs_table);
return err;
}
static int do_help(int argc, char **argv)
{
if (json_output) {
jsonw_null(json_wtr);
return 0;
}
fprintf(stderr,
"Usage: %1$s %2$s { show | list } [id BTF_ID]\n"
" %1$s %2$s dump BTF_SRC [format FORMAT]\n"
" %1$s %2$s help\n"
"\n"
" BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
bpftool: Introduce btf c dump sorting JIRA: https://issues.redhat.com/browse/RHEL-30774 commit 94133cf24bb33889aac267a7f0e3e6a08b8a8e5a Author: Mykyta Yatsenko <yatsenko@meta.com> Date: Tue May 14 14:12:21 2024 +0100 bpftool: Introduce btf c dump sorting Sort bpftool c dump output; aiming to simplify vmlinux.h diffing and forcing more natural type definitions ordering. Definitions are sorted first by their BTF kind ranks, then by their base type name and by their own name. Type ranks Assign ranks to btf kinds (defined in function btf_type_rank) to set next order: 1. Anonymous enums/enums64 2. Named enums/enums64 3. Trivial types typedefs (ints, then floats) 4. Structs/Unions 5. Function prototypes 6. Forward declarations Type rank is set to maximum for unnamed reference types, structs and unions to avoid emitting those types early. They will be emitted as part of the type chain starting with named type. Lexicographical ordering Each type is assigned a sort_name and own_name. sort_name is the resolved name of the final base type for reference types (typedef, pointer, array etc). Sorting by sort_name allows to group typedefs of the same base type. sort_name for non-reference type is the same as own_name. own_name is a direct name of particular type, is used as final sorting step. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Tested-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Quentin Monnet <qmo@kernel.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20240514131221.20585-1-yatsenko@meta.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Viktor Malik <vmalik@redhat.com>
2024-11-26 07:57:39 +00:00
" FORMAT := { raw | c [unsorted] }\n"
" " HELP_SPEC_MAP "\n"
" " HELP_SPEC_PROGRAM "\n"
" " HELP_SPEC_OPTIONS " |\n"
" {-B|--base-btf} }\n"
"",
bin_name, "btf");
return 0;
}
static const struct cmd cmds[] = {
{ "show", do_show },
{ "list", do_show },
{ "help", do_help },
{ "dump", do_dump },
{ 0 }
};
int do_btf(int argc, char **argv)
{
return cmd_select(cmds, argc, argv, do_help);
}