From: Eduard Zingerman <eddyz87@gmail.com>
To: bpf@vger.kernel.org, ast@kernel.org
Cc: andrii@kernel.org, daniel@iogearbox.net, kernel-team@fb.com,
yhs@fb.com, arnaldo.melo@gmail.com,
Eduard Zingerman <eddyz87@gmail.com>
Subject: [RFC bpf-next 03/12] libbpf: Support for BTF_DECL_TAG dump in C format
Date: Wed, 26 Oct 2022 01:27:52 +0300 [thread overview]
Message-ID: <20221025222802.2295103-4-eddyz87@gmail.com> (raw)
In-Reply-To: <20221025222802.2295103-1-eddyz87@gmail.com>
At C level BTF_DECL_TAGs are represented as __attribute__
declarations, e.g.:
struct foo {
...;
} __attribute__((btf_decl_tag("bar")));
This commit covers only decl tags attached to structs and unions.
BTF doc says that BTF_DECL_TAGs should follow a target type but this
is not enforced and tests don't honor this restriction.
This commit uses hash table to map types to the list of decl tags.
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/lib/bpf/btf_dump.c | 143 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 142 insertions(+), 1 deletion(-)
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index bf0cc0e986dd..9bfe2a4ae277 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -75,6 +75,15 @@ struct btf_dump_data {
bool is_array_char;
};
+/*
+ * An array of ids of BTF_DECL_TAG objects associated with a specific type.
+ */
+struct decl_tag_array {
+ __u16 cnt;
+ __u16 cap;
+ __u32 tag_ids[0];
+};
+
struct btf_dump {
const struct btf *btf;
btf_dump_printf_fn_t printf_fn;
@@ -111,6 +120,11 @@ struct btf_dump {
* name occurrences
*/
struct hashmap *ident_names;
+ /*
+ * maps type id to decl_tag_array, assume that relatively small
+ * fraction of types has btf_decl_tag's attached
+ */
+ struct hashmap *decl_tags;
/*
* data for typed display; allocated if needed.
*/
@@ -127,6 +141,26 @@ static bool str_equal_fn(const void *a, const void *b, void *ctx)
return strcmp(a, b) == 0;
}
+static size_t int_hash_fn(const void *key, void *ctx)
+{
+ int i;
+ size_t h = 0;
+ char *bytes = (char *)key;
+
+ for (i = 0; i < 4; ++i)
+ h = h * 31 + bytes[i];
+
+ return h;
+}
+
+static bool int_equal_fn(const void *a, const void *b, void *ctx)
+{
+ int *ia = (int *)a;
+ int *ib = (int *)b;
+
+ return *ia == *ib;
+}
+
static const char *btf_name_of(const struct btf_dump *d, __u32 name_off)
{
return btf__name_by_offset(d->btf, name_off);
@@ -143,6 +177,7 @@ static void btf_dump_printf(const struct btf_dump *d, const char *fmt, ...)
static int btf_dump_mark_referenced(struct btf_dump *d);
static int btf_dump_resize(struct btf_dump *d);
+static int btf_dump_assign_decl_tags(struct btf_dump *d);
struct btf_dump *btf_dump__new(const struct btf *btf,
btf_dump_printf_fn_t printf_fn,
@@ -179,11 +214,24 @@ struct btf_dump *btf_dump__new(const struct btf *btf,
d->ident_names = NULL;
goto err;
}
+ d->decl_tags = hashmap__new(int_hash_fn, int_equal_fn, NULL);
+ if (IS_ERR(d->decl_tags)) {
+ err = PTR_ERR(d->decl_tags);
+ d->decl_tags = NULL;
+ goto err;
+ }
err = btf_dump_resize(d);
if (err)
goto err;
+ err = btf_dump_assign_decl_tags(d);
+ if (err)
+ goto err;
+
+ if (err)
+ goto err;
+
return d;
err:
btf_dump__free(d);
@@ -232,7 +280,8 @@ static void btf_dump_free_names(struct hashmap *map)
void btf_dump__free(struct btf_dump *d)
{
- int i;
+ int i, bkt;
+ struct hashmap_entry *cur;
if (IS_ERR_OR_NULL(d))
return;
@@ -250,6 +299,9 @@ void btf_dump__free(struct btf_dump *d)
free(d->decl_stack);
btf_dump_free_names(d->type_names);
btf_dump_free_names(d->ident_names);
+ hashmap__for_each_entry(d->decl_tags, cur, bkt)
+ free(cur->value);
+ hashmap__free(d->decl_tags);
free(d);
}
@@ -373,6 +425,77 @@ static int btf_dump_mark_referenced(struct btf_dump *d)
return 0;
}
+static struct decl_tag_array *btf_dump_find_decl_tags(struct btf_dump *d, __u32 id)
+{
+ struct decl_tag_array *decl_tags = NULL;
+
+ hashmap__find(d->decl_tags, &id, (void **)&decl_tags);
+
+ return decl_tags;
+}
+
+static struct decl_tag_array *realloc_decl_tags(struct decl_tag_array *tags, __u16 new_cap)
+{
+ size_t new_size = sizeof(struct decl_tag_array) + new_cap * sizeof(__u32);
+ struct decl_tag_array *new_tags = (tags
+ ? realloc(tags, new_size)
+ : calloc(1, new_size));
+
+ if (!new_tags)
+ return NULL;
+
+ new_tags->cap = new_cap;
+
+ return new_tags;
+}
+
+/*
+ * Scans all BTF objects looking for BTF_KIND_DECL_TAG entries.
+ * The id's of the entries are stored in the `btf_dump.decl_tags` table,
+ * grouped by a target type.
+ */
+static int btf_dump_assign_decl_tags(struct btf_dump *d)
+{
+ int err;
+ __u32 id;
+ __u32 n = btf__type_cnt(d->btf);
+ __u32 new_capacity;
+ const struct btf_type *t;
+ struct decl_tag_array *decl_tags;
+
+ for (id = 0; id < n; id++) {
+ t = btf__type_by_id(d->btf, id);
+
+ if (btf_kind(t) != BTF_KIND_DECL_TAG)
+ continue;
+
+ decl_tags = btf_dump_find_decl_tags(d, t->type);
+ if (!decl_tags) {
+ decl_tags = realloc_decl_tags(NULL, 1);
+ if (!decl_tags)
+ return -ENOMEM;
+ err = hashmap__insert(d->decl_tags, &t->type, decl_tags,
+ HASHMAP_SET, NULL, NULL);
+ if (err)
+ return err;
+ } else if (decl_tags->cnt == decl_tags->cap) {
+ new_capacity = decl_tags->cap * 2;
+ if (new_capacity > 0xffff)
+ return -ERANGE;
+ decl_tags = realloc_decl_tags(decl_tags, new_capacity);
+ if (!decl_tags)
+ return -ENOMEM;
+ decl_tags->cap = new_capacity;
+ err = hashmap__update(d->decl_tags, &t->type, decl_tags, NULL, NULL);
+ if (err)
+ return err;
+ }
+ decl_tags->tag_ids[decl_tags->cnt++] = id;
+ }
+
+ return 0;
+}
+
static int btf_dump_add_emit_queue_id(struct btf_dump *d, __u32 id)
{
__u32 *new_queue;
@@ -899,6 +1022,23 @@ static void btf_dump_emit_bit_padding(const struct btf_dump *d,
}
}
+static void btf_dump_emit_decl_tags(struct btf_dump *d, __u32 id)
+{
+ struct decl_tag_array *decl_tags = btf_dump_find_decl_tags(d, id);
+ struct btf_type *decl_tag_t;
+ const char *decl_tag_text;
+ __u32 i;
+
+ if (!decl_tags)
+ return;
+
+ for (i = 0; i < decl_tags->cnt; ++i) {
+ decl_tag_t = btf_type_by_id(d->btf, decl_tags->tag_ids[i]);
+ decl_tag_text = btf__name_by_offset(d->btf, decl_tag_t->name_off);
+ btf_dump_printf(d, " __attribute__((btf_decl_tag(\"%s\")))", decl_tag_text);
+ }
+}
+
static void btf_dump_emit_struct_fwd(struct btf_dump *d, __u32 id,
const struct btf_type *t)
{
@@ -964,6 +1104,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
btf_dump_printf(d, "%s}", pfx(lvl));
if (packed)
btf_dump_printf(d, " __attribute__((packed))");
+ btf_dump_emit_decl_tags(d, id);
}
static const char *missing_base_types[][2] = {
--
2.34.1
next prev parent reply other threads:[~2022-10-25 22:28 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-25 22:27 [RFC bpf-next 00/12] Use uapi kernel headers with vmlinux.h Eduard Zingerman
2022-10-25 22:27 ` [RFC bpf-next 01/12] libbpf: Deduplicate unambigous standalone forward declarations Eduard Zingerman
2022-10-27 22:07 ` Andrii Nakryiko
2022-10-31 1:00 ` Eduard Zingerman
2022-10-31 15:49 ` Eduard Zingerman
2022-11-01 17:08 ` Alan Maguire
2022-11-01 17:37 ` Eduard Zingerman
2022-10-25 22:27 ` [RFC bpf-next 02/12] selftests/bpf: Tests for standalone forward BTF declarations deduplication Eduard Zingerman
2022-10-25 22:27 ` Eduard Zingerman [this message]
2022-10-27 22:36 ` [RFC bpf-next 03/12] libbpf: Support for BTF_DECL_TAG dump in C format Andrii Nakryiko
2022-10-25 22:27 ` [RFC bpf-next 04/12] selftests/bpf: Tests " Eduard Zingerman
2022-10-25 22:27 ` [RFC bpf-next 05/12] libbpf: Header guards for selected data structures in vmlinux.h Eduard Zingerman
2022-10-27 22:44 ` Andrii Nakryiko
2022-10-25 22:27 ` [RFC bpf-next 06/12] selftests/bpf: Tests for header guards printing in BTF dump Eduard Zingerman
2022-10-25 22:27 ` [RFC bpf-next 07/12] bpftool: Enable header guards generation Eduard Zingerman
2022-10-25 22:27 ` [RFC bpf-next 08/12] kbuild: Script to infer header guard values for uapi headers Eduard Zingerman
2022-10-27 22:51 ` Andrii Nakryiko
2022-10-25 22:27 ` [RFC bpf-next 09/12] kbuild: Header guards for types from include/uapi/*.h in kernel BTF Eduard Zingerman
2022-10-27 18:43 ` Yonghong Song
2022-10-27 18:55 ` Yonghong Song
2022-10-27 22:44 ` Yonghong Song
2022-10-28 0:00 ` Eduard Zingerman
2022-10-28 0:14 ` Mykola Lysenko
2022-10-28 1:23 ` Yonghong Song
2022-10-28 1:21 ` Yonghong Song
2022-10-25 22:27 ` [RFC bpf-next 10/12] selftests/bpf: Script to verify uapi headers usage with vmlinux.h Eduard Zingerman
2022-10-25 22:28 ` [RFC bpf-next 11/12] selftests/bpf: Known good uapi headers for test_uapi_headers.py Eduard Zingerman
2022-10-25 22:28 ` [RFC bpf-next 12/12] selftests/bpf: script for infer_header_guards.pl testing Eduard Zingerman
2022-10-25 23:46 ` [RFC bpf-next 00/12] Use uapi kernel headers with vmlinux.h Alexei Starovoitov
2022-10-26 22:46 ` Eduard Zingerman
2022-10-26 11:10 ` Alan Maguire
2022-10-26 23:54 ` Eduard Zingerman
2022-10-27 23:14 ` Andrii Nakryiko
2022-10-28 1:33 ` Yonghong Song
2022-10-28 17:13 ` Andrii Nakryiko
2022-10-28 18:56 ` Yonghong Song
2022-10-28 21:35 ` Andrii Nakryiko
2022-11-01 16:01 ` Alan Maguire
2022-11-01 18:35 ` Alexei Starovoitov
2022-11-01 19:21 ` Eduard Zingerman
2022-11-01 19:44 ` Alexei Starovoitov
2022-11-11 21:55 ` Eduard Zingerman
2022-11-14 7:52 ` Yonghong Song
2022-11-14 21:13 ` Eduard Zingerman
2022-11-14 21:50 ` Alexei Starovoitov
2022-11-16 2:01 ` Eduard Zingerman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221025222802.2295103-4-eddyz87@gmail.com \
--to=eddyz87@gmail.com \
--cc=andrii@kernel.org \
--cc=arnaldo.melo@gmail.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=yhs@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox