* [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers
@ 2025-02-12 20:15 Ihor Solodrai
2025-02-12 20:15 ` [PATCH v2 dwarves 1/4] btf_encoder: refactor btf_encoder__tag_kfuncs() Ihor Solodrai
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Ihor Solodrai @ 2025-02-12 20:15 UTC (permalink / raw)
To: dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, eddyz87, mykolal, kernel-team
This patch series implements emitting appropriate BTF type tags for
argument and return types of kfuncs marked with KF_ARENA_* flags.
For additional context see the description of BPF patch
"bpf: define KF_ARENA_* flags for bpf_arena kfuncs" [1].
The feature depends on recent changes in libbpf [2].
[1] https://lore.kernel.org/bpf/20250206003148.2308659-1-ihor.solodrai@linux.dev/
[2] https://lore.kernel.org/bpf/20250130201239.1429648-1-ihor.solodrai@linux.dev/
v1->v2:
* Rewrite patch #1 refactoring btf_encoder__tag_kfuncs(): now the
post-processing step is removed entirely, and kfuncs are tagged in
btf_encoder__add_func().
* Nits and renames in patch #2
* Add patch #4 editing man pages
v1: https://lore.kernel.org/dwarves/20250207021442.155703-1-ihor.solodrai@linux.dev/
Ihor Solodrai (4):
btf_encoder: refactor btf_encoder__tag_kfuncs()
btf_encoder: emit type tags for bpf_arena pointers
pahole: introduce --btf_feature=attributes
man-pages: describe attributes and remove reproducible_build
btf_encoder.c | 282 +++++++++++++++++++++++----------------------
dwarves.h | 1 +
man-pages/pahole.1 | 7 +-
pahole.c | 11 ++
4 files changed, 161 insertions(+), 140 deletions(-)
--
2.48.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 dwarves 1/4] btf_encoder: refactor btf_encoder__tag_kfuncs()
2025-02-12 20:15 [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
@ 2025-02-12 20:15 ` Ihor Solodrai
2025-02-19 3:25 ` Eduard Zingerman
2025-02-12 20:15 ` [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Ihor Solodrai @ 2025-02-12 20:15 UTC (permalink / raw)
To: dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, eddyz87, mykolal, kernel-team
btf_encoder__tag_kfuncs() is a post-processing step of BTF encoding,
executed right before BTF is deduped and dumped to the output.
Rewrite btf_encoder__tag_kfuncs() into btf_encoder__collect_kfuncs().
Now it only reads the .BTF_ids section of the ELF, collecting kfunc
information and adding it to corresponding elf_function structs. It is
executed in btf_encoder__new() if tag_kfuncs flag is set. This way
kfunc information is available within entire lifetime of the
btf_encoder.
BTF decl tags for kfuncs are added immediately after the function is
added to BTF in btf_encoder__add_func(). It's done by btf__tag_kfunc()
factored out from the btf_encoder__tag_kfunc().
As a result btf_encoder__tag_kfuncs(), its subroutines and struct
btf_func type are deleted, as they are no longer necessary.
Link: https://lore.kernel.org/dwarves/3782640a577e6945c86d6330bc8a05018a1e5c52.camel@gmail.com/
Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
btf_encoder.c | 192 +++++++++++++++-----------------------------------
1 file changed, 57 insertions(+), 135 deletions(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index 511c1ea..965e8f0 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -89,6 +89,8 @@ struct elf_function {
const char *name;
char *alias;
size_t prefixlen;
+ bool kfunc;
+ uint32_t kfunc_flags;
};
struct elf_secinfo {
@@ -145,11 +147,6 @@ struct btf_encoder {
struct list_head elf_functions_list;
};
-struct btf_func {
- const char *name;
- int type_id;
-};
-
/* Half open interval representing range of addresses containing kfuncs */
struct btf_kfunc_set_range {
uint64_t start;
@@ -1178,6 +1175,39 @@ out:
return err;
}
+static int btf__add_kfunc_decl_tag(struct btf *btf, const char *tag, __u32 id, const char *kfunc)
+{
+ int err = btf__add_decl_tag(btf, tag, id, -1);
+
+ if (err < 0) {
+ fprintf(stderr, "%s: failed to insert kfunc decl tag for '%s': %d\n",
+ __func__, kfunc, err);
+ return err;
+ }
+ return 0;
+}
+
+static int btf__tag_kfunc(struct btf *btf, struct elf_function *kfunc, __u32 btf_fn_id)
+{
+ int err;
+
+ /* Note we are unconditionally adding the btf_decl_tag even
+ * though vmlinux may already contain btf_decl_tags for kfuncs.
+ * We are ok to do this b/c we will later btf__dedup() to remove
+ * any duplicates.
+ */
+ err = btf__add_kfunc_decl_tag(btf, BTF_KFUNC_TYPE_TAG, btf_fn_id, kfunc->name);
+ if (err < 0)
+ return err;
+
+ if (kfunc->kfunc_flags & KF_FASTCALL) {
+ err = btf__add_kfunc_decl_tag(btf, BTF_FASTCALL_TAG, btf_fn_id, kfunc->name);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
struct btf_encoder_func_state *state)
{
@@ -1188,6 +1218,7 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
const char *value;
char tmp_value[KSYM_NAME_LEN];
uint16_t idx;
+ int err;
btf_fnproto_id = btf_encoder__add_func_proto(encoder, NULL, state);
name = func->alias ?: func->name;
@@ -1199,6 +1230,16 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
name, btf_fnproto_id < 0 ? "proto" : "func");
return -1;
}
+
+ if (func->kfunc && encoder->tag_kfuncs && !encoder->skip_encoding_decl_tag) {
+ err = btf__tag_kfunc(encoder->btf, func, btf_fn_id);
+ if (err < 0) {
+ fprintf(stderr, "%s: failed to tag kfunc '%s': %d\n",
+ __func__, func->name, err);
+ return err;
+ }
+ }
+
if (state->nr_annots == 0)
return 0;
@@ -1771,116 +1812,10 @@ static char *get_func_name(const char *sym)
return func;
}
-static int btf_func_cmp(const void *_a, const void *_b)
-{
- const struct btf_func *a = _a;
- const struct btf_func *b = _b;
-
- return strcmp(a->name, b->name);
-}
-
-/*
- * Collects all functions described in BTF.
- * Returns non-zero on error.
- */
-static int btf_encoder__collect_btf_funcs(struct btf_encoder *encoder, struct gobuffer *funcs)
-{
- struct btf *btf = encoder->btf;
- int nr_types, type_id;
- int err = -1;
-
- /* First collect all the func entries into an array */
- nr_types = btf__type_cnt(btf);
- for (type_id = 1; type_id < nr_types; type_id++) {
- const struct btf_type *type;
- struct btf_func func = {};
- const char *name;
-
- type = btf__type_by_id(btf, type_id);
- if (!type) {
- fprintf(stderr, "%s: malformed BTF, can't resolve type for ID %d\n",
- __func__, type_id);
- err = -EINVAL;
- goto out;
- }
-
- if (!btf_is_func(type))
- continue;
-
- name = btf__name_by_offset(btf, type->name_off);
- if (!name) {
- fprintf(stderr, "%s: malformed BTF, can't resolve name for ID %d\n",
- __func__, type_id);
- err = -EINVAL;
- goto out;
- }
-
- func.name = name;
- func.type_id = type_id;
- err = gobuffer__add(funcs, &func, sizeof(func));
- if (err < 0)
- goto out;
- }
-
- /* Now that we've collected funcs, sort them by name */
- gobuffer__sort(funcs, sizeof(struct btf_func), btf_func_cmp);
-
- err = 0;
-out:
- return err;
-}
-
-static int btf__add_kfunc_decl_tag(struct btf *btf, const char *tag, __u32 id, const char *kfunc)
-{
- int err = btf__add_decl_tag(btf, tag, id, -1);
-
- if (err < 0) {
- fprintf(stderr, "%s: failed to insert kfunc decl tag for '%s': %d\n",
- __func__, kfunc, err);
- return err;
- }
- return 0;
-}
-
-static int btf_encoder__tag_kfunc(struct btf_encoder *encoder, struct gobuffer *funcs, const char *kfunc, __u32 flags)
-{
- struct btf_func key = { .name = kfunc };
- struct btf *btf = encoder->btf;
- struct btf_func *target;
- const void *base;
- unsigned int cnt;
- int err;
-
- base = gobuffer__entries(funcs);
- cnt = gobuffer__nr_entries(funcs);
- target = bsearch(&key, base, cnt, sizeof(key), btf_func_cmp);
- if (!target) {
- fprintf(stderr, "%s: failed to find kfunc '%s' in BTF\n", __func__, kfunc);
- return -1;
- }
-
- /* Note we are unconditionally adding the btf_decl_tag even
- * though vmlinux may already contain btf_decl_tags for kfuncs.
- * We are ok to do this b/c we will later btf__dedup() to remove
- * any duplicates.
- */
- err = btf__add_kfunc_decl_tag(btf, BTF_KFUNC_TYPE_TAG, target->type_id, kfunc);
- if (err < 0)
- return err;
- if (flags & KF_FASTCALL) {
- err = btf__add_kfunc_decl_tag(btf, BTF_FASTCALL_TAG, target->type_id, kfunc);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-static int btf_encoder__tag_kfuncs(struct btf_encoder *encoder)
+static int btf_encoder__collect_kfuncs(struct btf_encoder *encoder)
{
const char *filename = encoder->source_filename;
struct gobuffer btf_kfunc_ranges = {};
- struct gobuffer btf_funcs = {};
Elf_Data *symbols = NULL;
Elf_Data *idlist = NULL;
Elf_Scn *symscn = NULL;
@@ -1977,12 +1912,6 @@ static int btf_encoder__tag_kfuncs(struct btf_encoder *encoder)
}
nr_syms = shdr.sh_size / shdr.sh_entsize;
- err = btf_encoder__collect_btf_funcs(encoder, &btf_funcs);
- if (err) {
- fprintf(stderr, "%s: failed to collect BTF funcs\n", __func__);
- goto out;
- }
-
/* First collect all kfunc set ranges.
*
* Note we choose not to sort these ranges and accept a linear
@@ -2015,12 +1944,12 @@ static int btf_encoder__tag_kfuncs(struct btf_encoder *encoder)
for (i = 0; i < nr_syms; i++) {
const struct btf_kfunc_set_range *ranges;
const struct btf_id_and_flag *pair;
+ struct elf_function *elf_fn;
unsigned int ranges_cnt;
char *func, *name;
ptrdiff_t off;
GElf_Sym sym;
bool found;
- int err;
int j;
if (!gelf_getsym(symbols, i, &sym)) {
@@ -2061,18 +1990,16 @@ static int btf_encoder__tag_kfuncs(struct btf_encoder *encoder)
continue;
}
- err = btf_encoder__tag_kfunc(encoder, &btf_funcs, func, pair->flags);
- if (err) {
- fprintf(stderr, "%s: failed to tag kfunc '%s'\n", __func__, func);
- free(func);
- goto out;
+ elf_fn = btf_encoder__find_function(encoder, func, 0);
+ if (elf_fn) {
+ elf_fn->kfunc = true;
+ elf_fn->kfunc_flags = pair->flags;
}
free(func);
}
err = 0;
out:
- __gobuffer__delete(&btf_funcs);
__gobuffer__delete(&btf_kfunc_ranges);
if (elf)
elf_end(elf);
@@ -2083,7 +2010,6 @@ out:
int btf_encoder__encode(struct btf_encoder *encoder, struct conf_load *conf)
{
- bool should_tag_kfuncs;
int err;
size_t shndx;
@@ -2099,15 +2025,6 @@ int btf_encoder__encode(struct btf_encoder *encoder, struct conf_load *conf)
if (btf__type_cnt(encoder->btf) == 1)
return 0;
- /* Note vmlinux may already contain btf_decl_tag's for kfuncs. So
- * take care to call this before btf_dedup().
- */
- should_tag_kfuncs = encoder->tag_kfuncs && !encoder->skip_encoding_decl_tag;
- if (should_tag_kfuncs && btf_encoder__tag_kfuncs(encoder)) {
- fprintf(stderr, "%s: failed to tag kfuncs!\n", __func__);
- return -1;
- }
-
if (btf__dedup(encoder->btf, NULL)) {
fprintf(stderr, "%s: btf__dedup failed!\n", __func__);
return -1;
@@ -2496,6 +2413,11 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
if (!found_percpu && encoder->verbose)
printf("%s: '%s' doesn't have '%s' section\n", __func__, cu->filename, PERCPU_SECTION);
+ if (encoder->tag_kfuncs) {
+ if (btf_encoder__collect_kfuncs(encoder))
+ goto out_delete;
+ }
+
if (encoder->verbose)
printf("File %s:\n", cu->filename);
}
--
2.48.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers
2025-02-12 20:15 [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
2025-02-12 20:15 ` [PATCH v2 dwarves 1/4] btf_encoder: refactor btf_encoder__tag_kfuncs() Ihor Solodrai
@ 2025-02-12 20:15 ` Ihor Solodrai
2025-02-19 4:36 ` Eduard Zingerman
2025-02-12 20:15 ` [PATCH v2 dwarves 3/4] pahole: introduce --btf_feature=attributes Ihor Solodrai
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Ihor Solodrai @ 2025-02-12 20:15 UTC (permalink / raw)
To: dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, eddyz87, mykolal, kernel-team
When adding a kfunc prototype to BTF, check for the flags indicating
bpf_arena pointers and emit a type tag encoding
__attribute__((address_space(1))) for them. This also requires
updating BTF type ids in the btf_encoder_func_state, which is done as
a side effect in the tagging functions.
This feature depends on recent update in libbpf, supporting arbitrarty
attribute encoding [1].
[1] https://lore.kernel.org/bpf/20250130201239.1429648-1-ihor.solodrai@linux.dev/
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
---
btf_encoder.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index 965e8f0..3cec106 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -40,7 +40,13 @@
#define BTF_SET8_KFUNCS (1 << 0)
#define BTF_KFUNC_TYPE_TAG "bpf_kfunc"
#define BTF_FASTCALL_TAG "bpf_fastcall"
-#define KF_FASTCALL (1 << 12)
+#define BPF_ARENA_ATTR "address_space(1)"
+
+/* kfunc flags, see include/linux/btf.h in the kernel source */
+#define KF_FASTCALL (1 << 12)
+#define KF_ARENA_RET (1 << 13)
+#define KF_ARENA_ARG1 (1 << 14)
+#define KF_ARENA_ARG2 (1 << 15)
struct btf_id_and_flag {
uint32_t id;
@@ -731,6 +737,78 @@ static int32_t btf_encoder__tag_type(struct btf_encoder *encoder, uint32_t tag_t
return encoder->type_id_off + tag_type;
}
+#if LIBBPF_MAJOR_VERSION >= 1 && LIBBPF_MINOR_VERSION >= 6
+static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id)
+{
+ const struct btf_type *ptr;
+ int tagged_type_id;
+
+ ptr = btf__type_by_id(btf, ptr_id);
+ if (!btf_is_ptr(ptr))
+ return -EINVAL;
+
+ tagged_type_id = btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr->type);
+ if (tagged_type_id < 0)
+ return tagged_type_id;
+
+ return btf__add_ptr(btf, tagged_type_id);
+}
+
+static int btf__tag_bpf_arena_arg(struct btf *btf, struct btf_encoder_func_state *state, int idx)
+{
+ int id;
+
+ if (state->nr_parms <= idx)
+ return -EINVAL;
+
+ id = btf__tag_bpf_arena_ptr(btf, state->parms[idx].type_id);
+ if (id < 0) {
+ btf__log_err(btf, BTF_KIND_TYPE_TAG, BPF_ARENA_ATTR, true, id,
+ "Error adding BPF_ARENA_ATTR for an argument of kfunc '%s'", state->elf->name);
+ return id;
+ }
+ state->parms[idx].type_id = id;
+
+ return id;
+}
+
+static int btf__add_bpf_arena_type_tags(struct btf *btf, struct btf_encoder_func_state *state)
+{
+ uint32_t flags = state->elf->kfunc_flags;
+ int ret_type_id;
+ int err;
+
+ if (KF_ARENA_RET & flags) {
+ ret_type_id = btf__tag_bpf_arena_ptr(btf, state->ret_type_id);
+ if (ret_type_id < 0) {
+ btf__log_err(btf, BTF_KIND_TYPE_TAG, BPF_ARENA_ATTR, true, ret_type_id,
+ "Error adding BPF_ARENA_ATTR for return type of kfunc '%s'", state->elf->name);
+ return ret_type_id;
+ }
+ state->ret_type_id = ret_type_id;
+ }
+
+ if (KF_ARENA_ARG1 & flags) {
+ err = btf__tag_bpf_arena_arg(btf, state, 0);
+ if (err < 0)
+ return err;
+ }
+
+ if (KF_ARENA_ARG2 & flags) {
+ err = btf__tag_bpf_arena_arg(btf, state, 1);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+#endif // LIBBPF_MAJOR_VERSION >= 1 && LIBBPF_MINOR_VERSION >= 6
+
+static inline bool is_kfunc_state(struct btf_encoder_func_state *state)
+{
+ return state && state->elf && state->elf->kfunc;
+}
+
static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype,
struct btf_encoder_func_state *state)
{
@@ -744,6 +822,12 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f
assert(ftype != NULL || state != NULL);
+#if LIBBPF_MAJOR_VERSION >= 1 && LIBBPF_MINOR_VERSION >= 6
+ if (is_kfunc_state(state) && encoder->tag_kfuncs)
+ if (btf__add_bpf_arena_type_tags(encoder->btf, state) < 0)
+ return -1;
+#endif
+
/* add btf_type for func_proto */
if (ftype) {
btf = encoder->btf;
--
2.48.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 dwarves 3/4] pahole: introduce --btf_feature=attributes
2025-02-12 20:15 [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
2025-02-12 20:15 ` [PATCH v2 dwarves 1/4] btf_encoder: refactor btf_encoder__tag_kfuncs() Ihor Solodrai
2025-02-12 20:15 ` [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
@ 2025-02-12 20:15 ` Ihor Solodrai
2025-02-19 5:30 ` Eduard Zingerman
2025-02-12 20:15 ` [PATCH v2 dwarves 4/4] man-pages: describe attributes and remove reproducible_build Ihor Solodrai
2025-02-13 13:16 ` [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Jiri Olsa
4 siblings, 1 reply; 11+ messages in thread
From: Ihor Solodrai @ 2025-02-12 20:15 UTC (permalink / raw)
To: dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, eddyz87, mykolal, kernel-team
Add a feature flag "attributes" (default: false) controlling whether
pahole is allowed to generate BTF attributes: type tags and decl tags
with kind_flag = 1.
This is necessary for backward compatibility, as BPF verifier does not
recognize tags with kind_flag = 1 prior to (at least) 6.14-rc1 [1].
[1] https://lore.kernel.org/bpf/20250130201239.1429648-1-ihor.solodrai@linux.dev/
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
---
btf_encoder.c | 6 ++++--
dwarves.h | 1 +
pahole.c | 11 +++++++++++
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index 3cec106..fc99ad2 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -136,7 +136,8 @@ struct btf_encoder {
gen_floats,
skip_encoding_decl_tag,
tag_kfuncs,
- gen_distilled_base;
+ gen_distilled_base,
+ encode_attributes;
uint32_t array_index_id;
struct elf_secinfo *secinfo;
size_t seccnt;
@@ -823,7 +824,7 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f
assert(ftype != NULL || state != NULL);
#if LIBBPF_MAJOR_VERSION >= 1 && LIBBPF_MINOR_VERSION >= 6
- if (is_kfunc_state(state) && encoder->tag_kfuncs)
+ if (is_kfunc_state(state) && encoder->tag_kfuncs && encoder->encode_attributes)
if (btf__add_bpf_arena_type_tags(encoder->btf, state) < 0)
return -1;
#endif
@@ -2417,6 +2418,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
encoder->skip_encoding_decl_tag = conf_load->skip_encoding_btf_decl_tag;
encoder->tag_kfuncs = conf_load->btf_decl_tag_kfuncs;
encoder->gen_distilled_base = conf_load->btf_gen_distilled_base;
+ encoder->encode_attributes = conf_load->btf_attributes;
encoder->verbose = verbose;
encoder->has_index_type = false;
encoder->need_index_type = false;
diff --git a/dwarves.h b/dwarves.h
index 8234e1a..99ed783 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -89,6 +89,7 @@ struct conf_load {
bool reproducible_build;
bool btf_decl_tag_kfuncs;
bool btf_gen_distilled_base;
+ bool btf_attributes;
uint8_t hashtable_bits;
uint8_t max_hashtable_bits;
uint16_t kabi_prefix_len;
diff --git a/pahole.c b/pahole.c
index af3e1cf..0bda249 100644
--- a/pahole.c
+++ b/pahole.c
@@ -1152,6 +1152,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
#define ARG_padding_ge 347
#define ARG_padding 348
#define ARGP_with_embedded_flexible_array 349
+#define ARGP_btf_attributes 350
/* --btf_features=feature1[,feature2,..] allows us to specify
* a list of requested BTF features or "default" to enable all default
@@ -1210,6 +1211,9 @@ struct btf_feature {
BTF_NON_DEFAULT_FEATURE(distilled_base, btf_gen_distilled_base, false),
#endif
BTF_NON_DEFAULT_FEATURE(global_var, encode_btf_global_vars, false),
+#if LIBBPF_MAJOR_VERSION >= 1 && LIBBPF_MINOR_VERSION >= 6
+ BTF_NON_DEFAULT_FEATURE(attributes, btf_attributes, false),
+#endif
};
#define BTF_MAX_FEATURE_STR 1024
@@ -1785,6 +1789,11 @@ static const struct argp_option pahole__options[] = {
.key = ARGP_running_kernel_vmlinux,
.doc = "Search for, possibly getting from a debuginfo server, a vmlinux matching the running kernel build-id (from /sys/kernel/notes)"
},
+ {
+ .name = "btf_attributes",
+ .key = ARGP_btf_attributes,
+ .doc = "Allow generation of attributes in BTF. Attributes are the type tags and decl tags with the kind_flag set to 1.",
+ },
{
.name = NULL,
}
@@ -1979,6 +1988,8 @@ static error_t pahole__options_parser(int key, char *arg,
show_supported_btf_features(stdout); exit(0);
case ARGP_btf_features_strict:
parse_btf_features(arg, true); break;
+ case ARGP_btf_attributes:
+ conf_load.btf_attributes = true; break;
default:
return ARGP_ERR_UNKNOWN;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 dwarves 4/4] man-pages: describe attributes and remove reproducible_build
2025-02-12 20:15 [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
` (2 preceding siblings ...)
2025-02-12 20:15 ` [PATCH v2 dwarves 3/4] pahole: introduce --btf_feature=attributes Ihor Solodrai
@ 2025-02-12 20:15 ` Ihor Solodrai
2025-02-13 13:16 ` [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Jiri Olsa
4 siblings, 0 replies; 11+ messages in thread
From: Ihor Solodrai @ 2025-02-12 20:15 UTC (permalink / raw)
To: dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, eddyz87, mykolal, kernel-team
Add a description of the new --btf_feature=attributes.
Also remove reproducible_build description, as it is now a moot
feature flag.
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
man-pages/pahole.1 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
index 39e7b46..3125de3 100644
--- a/man-pages/pahole.1
+++ b/man-pages/pahole.1
@@ -327,9 +327,10 @@ Encode BTF using the specified feature list, or specify 'default' for all standa
Supported non-standard features (not enabled for 'default')
.nf
- reproducible_build Ensure generated BTF is consistent every time;
- without this parallel BTF encoding can result in
- inconsistent BTF ids.
+ attributes Allow generation of decl_tags and type_tags with
+ kind_flag = 1. These tags can be used to encode
+ arbitrary compiler attributes in BTF, but are
+ backward incompatible.
decl_tag_kfuncs Inject a BTF_KIND_DECL_TAG for each discovered kfunc.
distilled_base For split BTF, generate a distilled version of
the associated base BTF to support later relocation
--
2.48.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers
2025-02-12 20:15 [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
` (3 preceding siblings ...)
2025-02-12 20:15 ` [PATCH v2 dwarves 4/4] man-pages: describe attributes and remove reproducible_build Ihor Solodrai
@ 2025-02-13 13:16 ` Jiri Olsa
4 siblings, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2025-02-13 13:16 UTC (permalink / raw)
To: Ihor Solodrai
Cc: dwarves, bpf, acme, alan.maguire, ast, andrii, eddyz87, mykolal,
kernel-team
On Wed, Feb 12, 2025 at 12:15:48PM -0800, Ihor Solodrai wrote:
> This patch series implements emitting appropriate BTF type tags for
> argument and return types of kfuncs marked with KF_ARENA_* flags.
>
> For additional context see the description of BPF patch
> "bpf: define KF_ARENA_* flags for bpf_arena kfuncs" [1].
>
> The feature depends on recent changes in libbpf [2].
>
> [1] https://lore.kernel.org/bpf/20250206003148.2308659-1-ihor.solodrai@linux.dev/
> [2] https://lore.kernel.org/bpf/20250130201239.1429648-1-ihor.solodrai@linux.dev/
>
> v1->v2:
> * Rewrite patch #1 refactoring btf_encoder__tag_kfuncs(): now the
> post-processing step is removed entirely, and kfuncs are tagged in
> btf_encoder__add_func().
> * Nits and renames in patch #2
> * Add patch #4 editing man pages
lgtm
Reviewed-by: Jiri Olsa <jolsa@kernel.org>
thanks,
jirka
>
> v1: https://lore.kernel.org/dwarves/20250207021442.155703-1-ihor.solodrai@linux.dev/
>
> Ihor Solodrai (4):
> btf_encoder: refactor btf_encoder__tag_kfuncs()
> btf_encoder: emit type tags for bpf_arena pointers
> pahole: introduce --btf_feature=attributes
> man-pages: describe attributes and remove reproducible_build
>
> btf_encoder.c | 282 +++++++++++++++++++++++----------------------
> dwarves.h | 1 +
> man-pages/pahole.1 | 7 +-
> pahole.c | 11 ++
> 4 files changed, 161 insertions(+), 140 deletions(-)
>
> --
> 2.48.1
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 dwarves 1/4] btf_encoder: refactor btf_encoder__tag_kfuncs()
2025-02-12 20:15 ` [PATCH v2 dwarves 1/4] btf_encoder: refactor btf_encoder__tag_kfuncs() Ihor Solodrai
@ 2025-02-19 3:25 ` Eduard Zingerman
0 siblings, 0 replies; 11+ messages in thread
From: Eduard Zingerman @ 2025-02-19 3:25 UTC (permalink / raw)
To: Ihor Solodrai, dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, mykolal, kernel-team
On Wed, 2025-02-12 at 12:15 -0800, Ihor Solodrai wrote:
> btf_encoder__tag_kfuncs() is a post-processing step of BTF encoding,
> executed right before BTF is deduped and dumped to the output.
>
> Rewrite btf_encoder__tag_kfuncs() into btf_encoder__collect_kfuncs().
> Now it only reads the .BTF_ids section of the ELF, collecting kfunc
> information and adding it to corresponding elf_function structs. It is
> executed in btf_encoder__new() if tag_kfuncs flag is set. This way
> kfunc information is available within entire lifetime of the
> btf_encoder.
>
> BTF decl tags for kfuncs are added immediately after the function is
> added to BTF in btf_encoder__add_func(). It's done by btf__tag_kfunc()
> factored out from the btf_encoder__tag_kfunc().
>
> As a result btf_encoder__tag_kfuncs(), its subroutines and struct
Nit: btf_encoder__collect_btf_funcs() is the one removed,
btf_encoder__tag_kfuncs is renamed.
> btf_func type are deleted, as they are no longer necessary.
>
> Link: https://lore.kernel.org/dwarves/3782640a577e6945c86d6330bc8a05018a1e5c52.camel@gmail.com/
>
> Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
> ---
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
[...]
> btf_encoder.c | 192 +++++++++++++++-----------------------------------
> 1 file changed, 57 insertions(+), 135 deletions(-)
>
> diff --git a/btf_encoder.c b/btf_encoder.c
> index 511c1ea..965e8f0 100644
> --- a/btf_encoder.c
> +++ b/btf_encoder.c
[...]
> @@ -1199,6 +1230,16 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder,
> name, btf_fnproto_id < 0 ? "proto" : "func");
> return -1;
> }
> +
> + if (func->kfunc && encoder->tag_kfuncs && !encoder->skip_encoding_decl_tag) {
> + err = btf__tag_kfunc(encoder->btf, func, btf_fn_id);
> + if (err < 0) {
> + fprintf(stderr, "%s: failed to tag kfunc '%s': %d\n",
> + __func__, func->name, err);
Nit: btf__tag_kfunc() already prints to stderr in case of an error,
this printf is unnecessary.
> + return err;
> + }
> + }
> +
> if (state->nr_annots == 0)
> return 0;
>
[...]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers
2025-02-12 20:15 ` [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
@ 2025-02-19 4:36 ` Eduard Zingerman
2025-02-19 5:45 ` Eduard Zingerman
0 siblings, 1 reply; 11+ messages in thread
From: Eduard Zingerman @ 2025-02-19 4:36 UTC (permalink / raw)
To: Ihor Solodrai, dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, mykolal, kernel-team
On Wed, 2025-02-12 at 12:15 -0800, Ihor Solodrai wrote:
[...]
> diff --git a/btf_encoder.c b/btf_encoder.c
> index 965e8f0..3cec106 100644
> --- a/btf_encoder.c
> +++ b/btf_encoder.c
[...]
> +static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id)
> +{
> + const struct btf_type *ptr;
> + int tagged_type_id;
> +
> + ptr = btf__type_by_id(btf, ptr_id);
> + if (!btf_is_ptr(ptr))
> + return -EINVAL;
> +
> + tagged_type_id = btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr->type);
> + if (tagged_type_id < 0)
> + return tagged_type_id;
> +
> + return btf__add_ptr(btf, tagged_type_id);
> +}
I might be confused, but this is a bit strange.
The type constructed here is: ptr -> type_tag -> t.
However, address_space is an attribute of a pointer, not a pointed type.
I think that correct sequence should be: type_tag -> ptr -> t.
This would make libbpf emit C declaration as follows:
void * __attribute__((address_space(1))) ptr;
Instead of current:
void __attribute__((address_space(1))) * ptr;
clang generates identical IR for both declarations:
@ptr = dso_local global ptr addrspace(1) null, align 8
Thus, imo, this function should be simplified as below:
static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id)
{
const struct btf_type *ptr;
ptr = btf__type_by_id(btf, ptr_id);
if (!btf_is_ptr(ptr))
return -EINVAL;
return btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr_id);
}
[...]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 dwarves 3/4] pahole: introduce --btf_feature=attributes
2025-02-12 20:15 ` [PATCH v2 dwarves 3/4] pahole: introduce --btf_feature=attributes Ihor Solodrai
@ 2025-02-19 5:30 ` Eduard Zingerman
0 siblings, 0 replies; 11+ messages in thread
From: Eduard Zingerman @ 2025-02-19 5:30 UTC (permalink / raw)
To: Ihor Solodrai, dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, mykolal, kernel-team
On Wed, 2025-02-12 at 12:15 -0800, Ihor Solodrai wrote:
> Add a feature flag "attributes" (default: false) controlling whether
> pahole is allowed to generate BTF attributes: type tags and decl tags
> with kind_flag = 1.
>
> This is necessary for backward compatibility, as BPF verifier does not
> recognize tags with kind_flag = 1 prior to (at least) 6.14-rc1 [1].
>
> [1] https://lore.kernel.org/bpf/20250130201239.1429648-1-ihor.solodrai@linux.dev/
>
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
> Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
> ---
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers
2025-02-19 4:36 ` Eduard Zingerman
@ 2025-02-19 5:45 ` Eduard Zingerman
2025-02-19 18:03 ` Ihor Solodrai
0 siblings, 1 reply; 11+ messages in thread
From: Eduard Zingerman @ 2025-02-19 5:45 UTC (permalink / raw)
To: Ihor Solodrai, dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, mykolal, kernel-team
On Tue, 2025-02-18 at 20:36 -0800, Eduard Zingerman wrote:
> On Wed, 2025-02-12 at 12:15 -0800, Ihor Solodrai wrote:
>
> [...]
>
> > diff --git a/btf_encoder.c b/btf_encoder.c
> > index 965e8f0..3cec106 100644
> > --- a/btf_encoder.c
> > +++ b/btf_encoder.c
>
> [...]
>
> > +static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id)
> > +{
> > + const struct btf_type *ptr;
> > + int tagged_type_id;
> > +
> > + ptr = btf__type_by_id(btf, ptr_id);
> > + if (!btf_is_ptr(ptr))
> > + return -EINVAL;
> > +
> > + tagged_type_id = btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr->type);
> > + if (tagged_type_id < 0)
> > + return tagged_type_id;
> > +
> > + return btf__add_ptr(btf, tagged_type_id);
> > +}
>
> I might be confused, but this is a bit strange.
> The type constructed here is: ptr -> type_tag -> t.
> However, address_space is an attribute of a pointer, not a pointed type.
> I think that correct sequence should be: type_tag -> ptr -> t.
> This would make libbpf emit C declaration as follows:
>
> void * __attribute__((address_space(1))) ptr;
>
> Instead of current:
>
> void __attribute__((address_space(1))) * ptr;
>
> clang generates identical IR for both declarations:
>
> @ptr = dso_local global ptr addrspace(1) null, align 8
>
> Thus, imo, this function should be simplified as below:
>
> static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id)
> {
> const struct btf_type *ptr;
>
> ptr = btf__type_by_id(btf, ptr_id);
> if (!btf_is_ptr(ptr))
> return -EINVAL;
>
> return btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr_id);
> }
>
> [...]
>
Ok, this comment can be ignored.
The following C code:
int foo(void * __attribute__((address_space(1))) ptr) {
return ptr != 0;
}
does not compile, with the following error reported:
test3.c:1:49: error: parameter may not be qualified with an address space
1 | int foo(void *__attribute__((address_space(1))) ptr) {
|
While the following works:
int foo(void __attribute__((address_space(1))) *ptr) {
return ptr != 0;
}
With the following IR generated:
define dso_local i32 @foo(ptr addrspace(1) noundef %0) #0 { ... }
Strange.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers
2025-02-19 5:45 ` Eduard Zingerman
@ 2025-02-19 18:03 ` Ihor Solodrai
0 siblings, 0 replies; 11+ messages in thread
From: Ihor Solodrai @ 2025-02-19 18:03 UTC (permalink / raw)
To: Eduard Zingerman, dwarves, bpf
Cc: acme, alan.maguire, ast, andrii, mykolal, kernel-team
On 2/18/25 9:45 PM, Eduard Zingerman wrote:
> On Tue, 2025-02-18 at 20:36 -0800, Eduard Zingerman wrote:
>> On Wed, 2025-02-12 at 12:15 -0800, Ihor Solodrai wrote:
>>
>> [...]
>>
>>> diff --git a/btf_encoder.c b/btf_encoder.c
>>> index 965e8f0..3cec106 100644
>>> --- a/btf_encoder.c
>>> +++ b/btf_encoder.c
>>
>> [...]
>>
>>> +static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id)
>>> +{
>>> + const struct btf_type *ptr;
>>> + int tagged_type_id;
>>> +
>>> + ptr = btf__type_by_id(btf, ptr_id);
>>> + if (!btf_is_ptr(ptr))
>>> + return -EINVAL;
>>> +
>>> + tagged_type_id = btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr->type);
>>> + if (tagged_type_id < 0)
>>> + return tagged_type_id;
>>> +
>>> + return btf__add_ptr(btf, tagged_type_id);
>>> +}
>>
>> I might be confused, but this is a bit strange.
>> The type constructed here is: ptr -> type_tag -> t.
>> However, address_space is an attribute of a pointer, not a pointed type.
>> I think that correct sequence should be: type_tag -> ptr -> t.
>> This would make libbpf emit C declaration as follows:
>>
>> void * __attribute__((address_space(1))) ptr;
>>
>> Instead of current:
>>
>> void __attribute__((address_space(1))) * ptr;
I was also confused about this.
The goal I had in mind is reproducing bpf_arena_* function
declarations, which are:
void __arena* bpf_arena_alloc_pages(void *map, void __arena *addr, __u32 page_cnt,
int node_id, __u64 flags) __ksym __weak;
void bpf_arena_free_pages(void *map, void __arena *ptr, __u32 page_cnt) __ksym __weak;
AFAIU this is by design. From BTF documentation[1]:
Currently, BTF_KIND_TYPE_TAG is only emitted for pointer types. It has
the following btf type chain:
ptr -> [type_tag]*
-> [const | volatile | restrict | typedef]*
-> base_type
Basically, a pointer type points to zero or more type_tag, then zero
or more const/volatile/restrict/typedef and finally the base type. The
base type is one of int, ptr, array, struct, union, enum, func_proto
and float types.
So yeah, unintuitively a tagged pointer in BTF is actually a pointer
to a tagged type. My guess is, it is so because of how C compilers
interpret type attributes, as evident by an example you've tested.
[1] https://docs.kernel.org/bpf/btf.html#btf-kind-type-tag
>>
>> clang generates identical IR for both declarations:
>>
>> @ptr = dso_local global ptr addrspace(1) null, align 8
>>
>> Thus, imo, this function should be simplified as below:
>>
>> static int btf__tag_bpf_arena_ptr(struct btf *btf, int ptr_id)
>> {
>> const struct btf_type *ptr;
>>
>> ptr = btf__type_by_id(btf, ptr_id);
>> if (!btf_is_ptr(ptr))
>> return -EINVAL;
>>
>> return btf__add_type_attr(btf, BPF_ARENA_ATTR, ptr_id);
>> }
>>
>> [...]
>>
>
> Ok, this comment can be ignored.
> The following C code:
>
> int foo(void * __attribute__((address_space(1))) ptr) {
> return ptr != 0;
> }
>
> does not compile, with the following error reported:
>
> test3.c:1:49: error: parameter may not be qualified with an address space
> 1 | int foo(void *__attribute__((address_space(1))) ptr) {
> |
>
> While the following works:
>
> int foo(void __attribute__((address_space(1))) *ptr) {
> return ptr != 0;
> }
>
> With the following IR generated:
>
> define dso_local i32 @foo(ptr addrspace(1) noundef %0) #0 { ... }
>
> Strange.
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-02-19 18:03 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-12 20:15 [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
2025-02-12 20:15 ` [PATCH v2 dwarves 1/4] btf_encoder: refactor btf_encoder__tag_kfuncs() Ihor Solodrai
2025-02-19 3:25 ` Eduard Zingerman
2025-02-12 20:15 ` [PATCH v2 dwarves 2/4] btf_encoder: emit type tags for bpf_arena pointers Ihor Solodrai
2025-02-19 4:36 ` Eduard Zingerman
2025-02-19 5:45 ` Eduard Zingerman
2025-02-19 18:03 ` Ihor Solodrai
2025-02-12 20:15 ` [PATCH v2 dwarves 3/4] pahole: introduce --btf_feature=attributes Ihor Solodrai
2025-02-19 5:30 ` Eduard Zingerman
2025-02-12 20:15 ` [PATCH v2 dwarves 4/4] man-pages: describe attributes and remove reproducible_build Ihor Solodrai
2025-02-13 13:16 ` [PATCH v2 dwarves 0/4] btf_encoder: emit type tags for bpf_arena pointers Jiri Olsa
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.