public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] tracing: resolve enum names for function arguments via BTF
@ 2026-02-02 11:15 Donglin Peng
  2026-02-02 11:15 ` [PATCH 1/2] btf: Add for_each_enum and for_each_enum64 helper macros Donglin Peng
  2026-02-02 11:15 ` [PATCH 2/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
  0 siblings, 2 replies; 23+ messages in thread
From: Donglin Peng @ 2026-02-02 11:15 UTC (permalink / raw)
  To: rostedt, ast; +Cc: mhiramat, andrii.nakryiko, linux-kernel, Donglin Peng

From: Donglin Peng <pengdonglin@xiaomi.com>

The print_function_args() function, used for function tracer output,
currently prints values of enum parameters in decimal format, which
reduces readability.

Utilize the BTF information to resolve enum type parameters and print
their symbolic names where possible. This enhances the trace log
readability by displaying meaningful identifiers instead of raw numbers.

Before:
count_memcg_events(memcg=0xffff888005740980, idx=20, count=0x1) {

After:
count_memcg_events(memcg=0xffff888005740980, idx=20 [PGFAULT], count=0x1) {

Donglin Peng (2):
  btf: Add for_each_enum and for_each_enum64 helper macros
  tracing: resolve enum names for function arguments via BTF

 include/linux/btf.h         | 10 ++++++
 kernel/bpf/btf.c            | 66 ++++++++++++++++---------------------
 kernel/trace/trace_output.c | 11 ++++++-
 3 files changed, 48 insertions(+), 39 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/2] btf: Add for_each_enum and for_each_enum64 helper macros
  2026-02-02 11:15 [PATCH 0/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
@ 2026-02-02 11:15 ` Donglin Peng
  2026-02-06  0:29   ` Masami Hiramatsu
  2026-02-02 11:15 ` [PATCH 2/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
  1 sibling, 1 reply; 23+ messages in thread
From: Donglin Peng @ 2026-02-02 11:15 UTC (permalink / raw)
  To: rostedt, ast
  Cc: mhiramat, andrii.nakryiko, linux-kernel, Donglin Peng,
	Andrii Nakryiko, Eduard Zingerman, bpf

From: Donglin Peng <pengdonglin@xiaomi.com>

Introduce two new helper macros, for_each_enum and for_each_enum64,
to clean up code.

No functional changes.

Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Eduard Zingerman <eddyz87@gmail.com>
Cc: bpf@vger.kernel.org
Signed-off-by: Donglin Peng <pengdonglin@xiaomi.com>
---
 include/linux/btf.h | 10 +++++++
 kernel/bpf/btf.c    | 66 +++++++++++++++++++--------------------------
 2 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/include/linux/btf.h b/include/linux/btf.h
index f06976ffb63f..cde2deb8e25e 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -254,6 +254,16 @@ const char *btf_type_str(const struct btf_type *t);
 	     i < btf_type_vlen(datasec_type);			\
 	     i++, member++)
 
+#define for_each_enum(i, enum_type, member)			\
+	for (i = 0, member = btf_enum(enum_type);		\
+	     i < btf_type_vlen(enum_type);			\
+	     i++, member++)
+
+#define for_each_enum64(i, enum_type, member)			\
+	for (i = 0, member = btf_enum64(enum_type);		\
+	     i < btf_type_vlen(enum_type);			\
+	     i++, member++)
+
 static inline bool btf_type_is_ptr(const struct btf_type *t)
 {
 	return BTF_INFO_KIND(t->info) == BTF_KIND_PTR;
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 0de8fc8a0e0b..c80a7a0cbe1d 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -728,11 +728,6 @@ static const struct btf_array *btf_type_array(const struct btf_type *t)
 	return (const struct btf_array *)(t + 1);
 }
 
-static const struct btf_enum *btf_type_enum(const struct btf_type *t)
-{
-	return (const struct btf_enum *)(t + 1);
-}
-
 static const struct btf_var *btf_type_var(const struct btf_type *t)
 {
 	return (const struct btf_var *)(t + 1);
@@ -743,11 +738,6 @@ static const struct btf_decl_tag *btf_type_decl_tag(const struct btf_type *t)
 	return (const struct btf_decl_tag *)(t + 1);
 }
 
-static const struct btf_enum64 *btf_type_enum64(const struct btf_type *t)
-{
-	return (const struct btf_enum64 *)(t + 1);
-}
-
 static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t)
 {
 	return kind_ops[BTF_INFO_KIND(t->info)];
@@ -4317,14 +4307,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
 			       const struct btf_type *t,
 			       u32 meta_left)
 {
-	const struct btf_enum *enums = btf_type_enum(t);
+	const struct btf_enum *enump;
 	struct btf *btf = env->btf;
 	const char *fmt_str;
 	u16 i, nr_enums;
 	u32 meta_needed;
 
 	nr_enums = btf_type_vlen(t);
-	meta_needed = nr_enums * sizeof(*enums);
+	meta_needed = nr_enums * sizeof(*enump);
 
 	if (meta_left < meta_needed) {
 		btf_verifier_log_basic(env, t,
@@ -4347,16 +4337,16 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
 
 	btf_verifier_log_type(env, t, NULL);
 
-	for (i = 0; i < nr_enums; i++) {
-		if (!btf_name_offset_valid(btf, enums[i].name_off)) {
+	for_each_enum(i, t, enump) {
+		if (!btf_name_offset_valid(btf, enump->name_off)) {
 			btf_verifier_log(env, "\tInvalid name_offset:%u",
-					 enums[i].name_off);
+					 enump->name_off);
 			return -EINVAL;
 		}
 
 		/* enum member must have a valid name */
-		if (!enums[i].name_off ||
-		    !btf_name_valid_identifier(btf, enums[i].name_off)) {
+		if (!enump->name_off ||
+		    !btf_name_valid_identifier(btf, enump->name_off)) {
 			btf_verifier_log_type(env, t, "Invalid name");
 			return -EINVAL;
 		}
@@ -4365,8 +4355,8 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
 			continue;
 		fmt_str = btf_type_kflag(t) ? "\t%s val=%d\n" : "\t%s val=%u\n";
 		btf_verifier_log(env, fmt_str,
-				 __btf_name_by_offset(btf, enums[i].name_off),
-				 enums[i].val);
+				 __btf_name_by_offset(btf, enump->name_off),
+				 enump->val);
 	}
 
 	return meta_needed;
@@ -4382,8 +4372,8 @@ static void btf_enum_show(const struct btf *btf, const struct btf_type *t,
 			  u32 type_id, void *data, u8 bits_offset,
 			  struct btf_show *show)
 {
-	const struct btf_enum *enums = btf_type_enum(t);
-	u32 i, nr_enums = btf_type_vlen(t);
+	const struct btf_enum *enump;
+	u32 i;
 	void *safe_data;
 	int v;
 
@@ -4393,13 +4383,13 @@ static void btf_enum_show(const struct btf *btf, const struct btf_type *t,
 
 	v = *(int *)safe_data;
 
-	for (i = 0; i < nr_enums; i++) {
-		if (v != enums[i].val)
+	for_each_enum(i, t, enump) {
+		if (v != enump->val)
 			continue;
 
 		btf_show_type_value(show, "%s",
 				    __btf_name_by_offset(btf,
-							 enums[i].name_off));
+							 enump->name_off));
 
 		btf_show_end_type(show);
 		return;
@@ -4425,14 +4415,14 @@ static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
 				 const struct btf_type *t,
 				 u32 meta_left)
 {
-	const struct btf_enum64 *enums = btf_type_enum64(t);
+	const struct btf_enum64 *enump;
 	struct btf *btf = env->btf;
 	const char *fmt_str;
 	u16 i, nr_enums;
 	u32 meta_needed;
 
 	nr_enums = btf_type_vlen(t);
-	meta_needed = nr_enums * sizeof(*enums);
+	meta_needed = nr_enums * sizeof(*enump);
 
 	if (meta_left < meta_needed) {
 		btf_verifier_log_basic(env, t,
@@ -4455,16 +4445,16 @@ static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
 
 	btf_verifier_log_type(env, t, NULL);
 
-	for (i = 0; i < nr_enums; i++) {
-		if (!btf_name_offset_valid(btf, enums[i].name_off)) {
+	for_each_enum64(i, t, enump) {
+		if (!btf_name_offset_valid(btf, enump->name_off)) {
 			btf_verifier_log(env, "\tInvalid name_offset:%u",
-					 enums[i].name_off);
+					 enump->name_off);
 			return -EINVAL;
 		}
 
 		/* enum member must have a valid name */
-		if (!enums[i].name_off ||
-		    !btf_name_valid_identifier(btf, enums[i].name_off)) {
+		if (!enump->name_off ||
+		    !btf_name_valid_identifier(btf, enump->name_off)) {
 			btf_verifier_log_type(env, t, "Invalid name");
 			return -EINVAL;
 		}
@@ -4474,8 +4464,8 @@ static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
 
 		fmt_str = btf_type_kflag(t) ? "\t%s val=%lld\n" : "\t%s val=%llu\n";
 		btf_verifier_log(env, fmt_str,
-				 __btf_name_by_offset(btf, enums[i].name_off),
-				 btf_enum64_value(enums + i));
+				 __btf_name_by_offset(btf, enump->name_off),
+				 btf_enum64_value(enump));
 	}
 
 	return meta_needed;
@@ -4485,8 +4475,8 @@ static void btf_enum64_show(const struct btf *btf, const struct btf_type *t,
 			    u32 type_id, void *data, u8 bits_offset,
 			    struct btf_show *show)
 {
-	const struct btf_enum64 *enums = btf_type_enum64(t);
-	u32 i, nr_enums = btf_type_vlen(t);
+	const struct btf_enum64 *enump;
+	u32 i;
 	void *safe_data;
 	s64 v;
 
@@ -4496,13 +4486,13 @@ static void btf_enum64_show(const struct btf *btf, const struct btf_type *t,
 
 	v = *(u64 *)safe_data;
 
-	for (i = 0; i < nr_enums; i++) {
-		if (v != btf_enum64_value(enums + i))
+	for_each_enum64(i, t, enump) {
+		if (v != btf_enum64_value(enump))
 			continue;
 
 		btf_show_type_value(show, "%s",
 				    __btf_name_by_offset(btf,
-							 enums[i].name_off));
+							 enump->name_off));
 
 		btf_show_end_type(show);
 		return;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-02 11:15 [PATCH 0/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
  2026-02-02 11:15 ` [PATCH 1/2] btf: Add for_each_enum and for_each_enum64 helper macros Donglin Peng
@ 2026-02-02 11:15 ` Donglin Peng
  2026-02-02 16:12   ` Steven Rostedt
  2026-02-06  0:12   ` Masami Hiramatsu
  1 sibling, 2 replies; 23+ messages in thread
From: Donglin Peng @ 2026-02-02 11:15 UTC (permalink / raw)
  To: rostedt, ast
  Cc: mhiramat, andrii.nakryiko, linux-kernel, Donglin Peng,
	linux-trace-kernel

From: Donglin Peng <pengdonglin@xiaomi.com>

Use BTF to print symbolic names for enum-type function arguments,
improving trace readability.

Before:
count_memcg_events(memcg=0xffff..., idx=20, count=0x1) {

After:
count_memcg_events(memcg=0xffff..., idx=20 [PGFAULT], count=0x1) {

Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: linux-trace-kernel@vger.kernel.org
Signed-off-by: Donglin Peng <pengdonglin@xiaomi.com>
---
 kernel/trace/trace_output.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index cc2d3306bb60..c395f768c3b8 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -695,12 +695,13 @@ void print_function_args(struct trace_seq *s, unsigned long *args,
 {
 	const struct btf_param *param;
 	const struct btf_type *t;
+	const struct btf_enum *enump;
 	const char *param_name;
 	char name[KSYM_NAME_LEN];
 	unsigned long arg;
 	struct btf *btf;
 	s32 tid, nr = 0;
-	int a, p, x;
+	int a, p, x, i;
 	u16 encode;
 
 	trace_seq_printf(s, "(");
@@ -754,6 +755,14 @@ void print_function_args(struct trace_seq *s, unsigned long *args,
 			break;
 		case BTF_KIND_ENUM:
 			trace_seq_printf(s, "%ld", arg);
+			for_each_enum(i, t, enump) {
+				if (arg == enump->val) {
+					trace_seq_printf(s, " [%s]",
+							 btf_name_by_offset(btf,
+							 enump->name_off));
+					break;
+				}
+			}
 			break;
 		default:
 			/* This does not handle complex arguments */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-02 11:15 ` [PATCH 2/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
@ 2026-02-02 16:12   ` Steven Rostedt
  2026-02-03  2:17     ` Donglin Peng
  2026-02-06  0:12   ` Masami Hiramatsu
  1 sibling, 1 reply; 23+ messages in thread
From: Steven Rostedt @ 2026-02-02 16:12 UTC (permalink / raw)
  To: Donglin Peng
  Cc: ast, mhiramat, andrii.nakryiko, linux-kernel, Donglin Peng,
	linux-trace-kernel

On Mon,  2 Feb 2026 19:15:48 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> @@ -754,6 +755,14 @@ void print_function_args(struct trace_seq *s, unsigned long *args,
>  			break;
>  		case BTF_KIND_ENUM:
>  			trace_seq_printf(s, "%ld", arg);
> +			for_each_enum(i, t, enump) {
> +				if (arg == enump->val) {
> +					trace_seq_printf(s, " [%s]",
> +							 btf_name_by_offset(btf,
> +							 enump->name_off));
> +					break;
> +				}
> +			}
>  			break;

I have to ask; how big is that enum list?

Do we really want to do a linear search for every enum we come across?

What we could do is for the first time we hit an enum, create an array of
enums, sort them, and do a binary search from then on. This could be saved
in the tracing code itself (in kernel/trace/trace_btf.c), if BPF doesn't
care about it.

-- Steve

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-02 16:12   ` Steven Rostedt
@ 2026-02-03  2:17     ` Donglin Peng
  2026-02-03 13:50       ` Donglin Peng
  0 siblings, 1 reply; 23+ messages in thread
From: Donglin Peng @ 2026-02-03  2:17 UTC (permalink / raw)
  To: Steven Rostedt, andrii.nakryiko
  Cc: ast, mhiramat, linux-kernel, Donglin Peng, linux-trace-kernel

On Tue, Feb 3, 2026 at 12:12 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Mon,  2 Feb 2026 19:15:48 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> > @@ -754,6 +755,14 @@ void print_function_args(struct trace_seq *s, unsigned long *args,
> >                       break;
> >               case BTF_KIND_ENUM:
> >                       trace_seq_printf(s, "%ld", arg);
> > +                     for_each_enum(i, t, enump) {
> > +                             if (arg == enump->val) {
> > +                                     trace_seq_printf(s, " [%s]",
> > +                                                      btf_name_by_offset(btf,
> > +                                                      enump->name_off));
> > +                                     break;
> > +                             }
> > +                     }
> >                       break;
>
> I have to ask; how big is that enum list?

Based on local vmlinux analysis (6.18 kernel):
- 78% enums have vlen ≤ 10
- 95% enums have vlen ≤ 50
- Max observed vlen: 349 (extremely rare case)

$ bpftool btf dump file x86_64/vmlinux | grep "^\[" | grep ENUM | grep
-v "(anon)" | awk -F '[ =]' '{
    for(i=1; i<=NF; i++) {
        if ($i == "vlen") {
            count[$(i+1)]++
        }
    }
}
END {
    for (vlen in count) {
        print "vlen=" vlen ": " count[vlen] " times"
    }
}' | sort -k 2 -n
vlen=104: 1 times
vlen=114: 1 times
vlen=116: 1 times
vlen=129: 1 times
vlen=146: 1 times
vlen=167: 1 times
vlen=181: 1 times
vlen=183: 1 times
vlen=201: 1 times
vlen=213: 1 times
vlen=33: 1 times
vlen=349: 1 times
vlen=42: 1 times
vlen=45: 1 times
vlen=48: 1 times
vlen=50: 1 times
vlen=54: 1 times
vlen=55: 1 times
vlen=56: 1 times
vlen=59: 1 times
vlen=60: 1 times
vlen=61: 1 times
vlen=64: 1 times
vlen=68: 1 times
vlen=71: 1 times
vlen=74: 1 times
vlen=83: 1 times
vlen=85: 1 times
vlen=87: 1 times
vlen=122: 2 times
vlen=38: 2 times
vlen=39: 2 times
vlen=43: 2 times
vlen=44: 2 times
vlen=49: 2 times
vlen=52: 2 times
vlen=58: 2 times
vlen=73: 2 times
vlen=79: 2 times
vlen=35: 3 times
vlen=41: 3 times
vlen=46: 3 times
vlen=25: 4 times
vlen=27: 4 times
vlen=28: 4 times
vlen=29: 4 times
vlen=34: 4 times
vlen=37: 4 times
vlen=40: 4 times
vlen=19: 5 times
vlen=30: 5 times
vlen=20: 6 times
vlen=22: 6 times
vlen=24: 6 times
vlen=16: 8 times
vlen=23: 8 times
vlen=26: 8 times
vlen=31: 8 times
vlen=32: 8 times
vlen=17: 11 times
vlen=18: 12 times
vlen=21: 12 times
vlen=15: 13 times
vlen=14: 21 times
vlen=12: 25 times
vlen=13: 25 times
vlen=10: 34 times
vlen=11: 35 times
vlen=1: 58 times
vlen=8: 70 times
vlen=9: 74 times
vlen=7: 102 times
vlen=6: 108 times
vlen=5: 170 times
vlen=2: 193 times
vlen=4: 250 times
vlen=3: 333 times

>
> Do we really want to do a linear search for every enum we come across?

I think linear search is efficient for typical enum value lists (vlen < 10), I
also support using binary search where feasible.

>
> What we could do is for the first time we hit an enum, create an array of
> enums, sort them, and do a binary search from then on. This could be saved
> in the tracing code itself (in kernel/trace/trace_btf.c), if BPF doesn't
> care about it.

I think this approach adds unnecessary complexity. Instead, we could
leverage btf2btf during the resolve_btfids phase to proactively sort the
btf_enum entries of enum-type btf_type by their value, enabling efficient
binary search lookups.

>
> -- Steve

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-03  2:17     ` Donglin Peng
@ 2026-02-03 13:50       ` Donglin Peng
  2026-02-03 15:17         ` Steven Rostedt
  0 siblings, 1 reply; 23+ messages in thread
From: Donglin Peng @ 2026-02-03 13:50 UTC (permalink / raw)
  To: Steven Rostedt, andrii.nakryiko
  Cc: ast, mhiramat, linux-kernel, Donglin Peng, linux-trace-kernel,
	bpf, Eduard Zingerman

On Tue, Feb 3, 2026 at 10:17 AM Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> On Tue, Feb 3, 2026 at 12:12 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> >
> > On Mon,  2 Feb 2026 19:15:48 +0800
> > Donglin Peng <dolinux.peng@gmail.com> wrote:
> >
> > > @@ -754,6 +755,14 @@ void print_function_args(struct trace_seq *s, unsigned long *args,
> > >                       break;
> > >               case BTF_KIND_ENUM:
> > >                       trace_seq_printf(s, "%ld", arg);
> > > +                     for_each_enum(i, t, enump) {
> > > +                             if (arg == enump->val) {
> > > +                                     trace_seq_printf(s, " [%s]",
> > > +                                                      btf_name_by_offset(btf,
> > > +                                                      enump->name_off));
> > > +                                     break;
> > > +                             }
> > > +                     }
> > >                       break;
> >
> > I have to ask; how big is that enum list?
>
> Based on local vmlinux analysis (6.18 kernel):
> - 78% enums have vlen ≤ 10
> - 95% enums have vlen ≤ 50
> - Max observed vlen: 349 (extremely rare case)
>
> $ bpftool btf dump file x86_64/vmlinux | grep "^\[" | grep ENUM | grep
> -v "(anon)" | awk -F '[ =]' '{
>     for(i=1; i<=NF; i++) {
>         if ($i == "vlen") {
>             count[$(i+1)]++
>         }
>     }
> }
> END {
>     for (vlen in count) {
>         print "vlen=" vlen ": " count[vlen] " times"
>     }
> }' | sort -k 2 -n
> vlen=104: 1 times
> vlen=114: 1 times
> vlen=116: 1 times
> vlen=129: 1 times
> vlen=146: 1 times
> vlen=167: 1 times
> vlen=181: 1 times
> vlen=183: 1 times
> vlen=201: 1 times
> vlen=213: 1 times
> vlen=33: 1 times
> vlen=349: 1 times
> vlen=42: 1 times
> vlen=45: 1 times
> vlen=48: 1 times
> vlen=50: 1 times
> vlen=54: 1 times
> vlen=55: 1 times
> vlen=56: 1 times
> vlen=59: 1 times
> vlen=60: 1 times
> vlen=61: 1 times
> vlen=64: 1 times
> vlen=68: 1 times
> vlen=71: 1 times
> vlen=74: 1 times
> vlen=83: 1 times
> vlen=85: 1 times
> vlen=87: 1 times
> vlen=122: 2 times
> vlen=38: 2 times
> vlen=39: 2 times
> vlen=43: 2 times
> vlen=44: 2 times
> vlen=49: 2 times
> vlen=52: 2 times
> vlen=58: 2 times
> vlen=73: 2 times
> vlen=79: 2 times
> vlen=35: 3 times
> vlen=41: 3 times
> vlen=46: 3 times
> vlen=25: 4 times
> vlen=27: 4 times
> vlen=28: 4 times
> vlen=29: 4 times
> vlen=34: 4 times
> vlen=37: 4 times
> vlen=40: 4 times
> vlen=19: 5 times
> vlen=30: 5 times
> vlen=20: 6 times
> vlen=22: 6 times
> vlen=24: 6 times
> vlen=16: 8 times
> vlen=23: 8 times
> vlen=26: 8 times
> vlen=31: 8 times
> vlen=32: 8 times
> vlen=17: 11 times
> vlen=18: 12 times
> vlen=21: 12 times
> vlen=15: 13 times
> vlen=14: 21 times
> vlen=12: 25 times
> vlen=13: 25 times
> vlen=10: 34 times
> vlen=11: 35 times
> vlen=1: 58 times
> vlen=8: 70 times
> vlen=9: 74 times
> vlen=7: 102 times
> vlen=6: 108 times
> vlen=5: 170 times
> vlen=2: 193 times
> vlen=4: 250 times
> vlen=3: 333 times
>
> >
> > Do we really want to do a linear search for every enum we come across?
>
> I think linear search is efficient for typical enum value lists (vlen < 10), I
> also support using binary search where feasible.
>
> >
> > What we could do is for the first time we hit an enum, create an array of
> > enums, sort them, and do a binary search from then on. This could be saved
> > in the tracing code itself (in kernel/trace/trace_btf.c), if BPF doesn't
> > care about it.
>
> I think this approach adds unnecessary complexity. Instead, we could
> leverage btf2btf during the resolve_btfids phase to proactively sort the
> btf_enum entries of enum-type btf_type by their value, enabling efficient
> binary search lookups.

Testing revealed that sorting within resolve_btfids introduces issues with
btf__dedup. Therefore, I plan to move the sorting logic directly into
btf__add_enum_value and btf__add_enum64_value in libbpf, which are
invoked by pahole. However, it means that we need a newer pahole
version.

>
> >
> > -- Steve

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-03 13:50       ` Donglin Peng
@ 2026-02-03 15:17         ` Steven Rostedt
  2026-02-03 16:00           ` Alexei Starovoitov
  2026-02-04 14:16           ` Donglin Peng
  0 siblings, 2 replies; 23+ messages in thread
From: Steven Rostedt @ 2026-02-03 15:17 UTC (permalink / raw)
  To: Donglin Peng
  Cc: andrii.nakryiko, ast, mhiramat, linux-kernel, Donglin Peng,
	linux-trace-kernel, bpf, Eduard Zingerman

On Tue, 3 Feb 2026 21:50:47 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> Testing revealed that sorting within resolve_btfids introduces issues with
> btf__dedup. Therefore, I plan to move the sorting logic directly into
> btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> invoked by pahole. However, it means that we need a newer pahole
> version.

Sorting isn't a requirement just something I wanted to bring up. If it's
too complex and doesn't achieve much benefit then let's not do it.

My worry is because "cat trace" takes quite a long time just reading the
BTF arguments. I'm worried it will just get worse with enums as well.

I have trace-cmd reading BTF now (just haven't officially released it) and
doing an extract and reading the trace.dat file is much faster than reading
the trace file with arguments. I'll need to implement the enum logic too in
libtraceevent.

-- Steve

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-03 15:17         ` Steven Rostedt
@ 2026-02-03 16:00           ` Alexei Starovoitov
  2026-02-04 14:52             ` Donglin Peng
  2026-02-04 14:16           ` Donglin Peng
  1 sibling, 1 reply; 23+ messages in thread
From: Alexei Starovoitov @ 2026-02-03 16:00 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Donglin Peng, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Tue, 3 Feb 2026 21:50:47 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> > Testing revealed that sorting within resolve_btfids introduces issues with
> > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > invoked by pahole. However, it means that we need a newer pahole
> > version.
>
> Sorting isn't a requirement just something I wanted to bring up. If it's
> too complex and doesn't achieve much benefit then let's not do it.
>
> My worry is because "cat trace" takes quite a long time just reading the
> BTF arguments. I'm worried it will just get worse with enums as well.
>
> I have trace-cmd reading BTF now (just haven't officially released it) and
> doing an extract and reading the trace.dat file is much faster than reading
> the trace file with arguments. I'll need to implement the enum logic too in
> libtraceevent.

If you mean to do pretty printing of the trace in user space then +1 from me.

I don't like sorting enums either in resolve_btfid, pahole or kernel.
Sorted BTF by name was ok, since it doesn't change original semantics.
While sorting enums by value gets us to the grey zone where
the sequence of enum names in vmlinux.h becomes different than in dwarf.

Also id->name mapping in general is not precise.
There is no requirement for enums to be unique.
Just grabbing the first one:
ATA_PIO0 = 1,
ATA_PIO1 = 3,
ATA_PIO2 = 7,
ATA_UDMA0 = 1,
ATA_UDMA1 = 3,
ATA_UDMA2 = 7,
ATA_ID_CYLS = 1,
ATA_ID_HEADS = 3,
SCR_ERROR = 1,
SCR_CONTROL = 2,
SCR_ACTIVE = 3,

All these names are part of the same enum type.
Which one to print? First one?

another example:
enum {
        BPF_LOCAL_STORAGE_GET_F_CREATE = 1,
        BPF_SK_STORAGE_GET_F_CREATE = 1,
};

and another:
enum {
        BPF_SKB_TSTAMP_UNSPEC = 0,
        BPF_SKB_TSTAMP_DELIVERY_MONO = 1,
        BPF_SKB_CLOCK_REALTIME = 0,
        BPF_SKB_CLOCK_MONOTONIC = 1,
        BPF_SKB_CLOCK_TAI = 2,
};

I'd rather not print any and keep it integer only.

pw-bot: cr

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-03 15:17         ` Steven Rostedt
  2026-02-03 16:00           ` Alexei Starovoitov
@ 2026-02-04 14:16           ` Donglin Peng
  1 sibling, 0 replies; 23+ messages in thread
From: Donglin Peng @ 2026-02-04 14:16 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: andrii.nakryiko, ast, mhiramat, linux-kernel, Donglin Peng,
	linux-trace-kernel, bpf, Eduard Zingerman

On Tue, Feb 3, 2026 at 11:16 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Tue, 3 Feb 2026 21:50:47 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> > Testing revealed that sorting within resolve_btfids introduces issues with
> > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > invoked by pahole. However, it means that we need a newer pahole
> > version.
>
> Sorting isn't a requirement just something I wanted to bring up. If it's
> too complex and doesn't achieve much benefit then let's not do it.

Thanks for clarifying. Analysis shows most enum-type btf_type have
small vlen (78% ≤ 10, 95% ≤50), so I think that  linear search could
be acceptable.

>
> My worry is because "cat trace" takes quite a long time just reading the
> BTF arguments. I'm worried it will just get worse with enums as well.

The delay stems from `btf_find_by_name_kind`’s linear search over
vmlinux BTF (10k+ types). This was resolved by adding binary search
to `btf_find_by_name_kind` [1].

Performance tests [2] confirm the improvement:
1. Original funcgraph-retval:
# time cat trace | wc -l
101024

real    0m0.682s
user    0m0.000s
sys     0m0.695s

2. Enhanced funcgraph-retval:
# time cat trace | wc -l
99326

real    0m12.886s
user    0m0.010s
sys     0m12.680s

3. Enhanced funcgraph-retval + optimizined btf_find_by_name_kind:
# time cat trace | wc -l
102922

real    0m0.794s
user    0m0.000s
sys     0m0.810s

Binary search reduces overhead to near-negligible levels (0.794s vs. 12.886s).

[1] https://lore.kernel.org/bpf/20260109130003.3313716-1-dolinux.peng@gmail.com/
[2] https://lore.kernel.org/lkml/20251209121349.525641-1-dolinux.peng@gmail.com/

>
> I have trace-cmd reading BTF now (just haven't officially released it) and
> doing an extract and reading the trace.dat file is much faster than reading
> the trace file with arguments. I'll need to implement the enum logic too in
> libtraceevent.
>
> -- Steve

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-03 16:00           ` Alexei Starovoitov
@ 2026-02-04 14:52             ` Donglin Peng
  2026-02-05  9:21               ` Donglin Peng
  2026-02-05 18:04               ` Steven Rostedt
  0 siblings, 2 replies; 23+ messages in thread
From: Donglin Peng @ 2026-02-04 14:52 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Steven Rostedt, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Wed, Feb 4, 2026 at 12:00 AM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> >
> > On Tue, 3 Feb 2026 21:50:47 +0800
> > Donglin Peng <dolinux.peng@gmail.com> wrote:
> >
> > > Testing revealed that sorting within resolve_btfids introduces issues with
> > > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > > invoked by pahole. However, it means that we need a newer pahole
> > > version.
> >
> > Sorting isn't a requirement just something I wanted to bring up. If it's
> > too complex and doesn't achieve much benefit then let's not do it.
> >
> > My worry is because "cat trace" takes quite a long time just reading the
> > BTF arguments. I'm worried it will just get worse with enums as well.
> >
> > I have trace-cmd reading BTF now (just haven't officially released it) and
> > doing an extract and reading the trace.dat file is much faster than reading
> > the trace file with arguments. I'll need to implement the enum logic too in
> > libtraceevent.
>
> If you mean to do pretty printing of the trace in user space then +1 from me.
>
> I don't like sorting enums either in resolve_btfid, pahole or kernel.
> Sorted BTF by name was ok, since it doesn't change original semantics.
> While sorting enums by value gets us to the grey zone where
> the sequence of enum names in vmlinux.h becomes different than in dwarf.

Thanks, I agreed.

>
> Also id->name mapping in general is not precise.
> There is no requirement for enums to be unique.
> Just grabbing the first one:
> ATA_PIO0 = 1,
> ATA_PIO1 = 3,
> ATA_PIO2 = 7,
> ATA_UDMA0 = 1,
> ATA_UDMA1 = 3,
> ATA_UDMA2 = 7,
> ATA_ID_CYLS = 1,
> ATA_ID_HEADS = 3,
> SCR_ERROR = 1,
> SCR_CONTROL = 2,
> SCR_ACTIVE = 3,
>
> All these names are part of the same enum type.
> Which one to print? First one?

I think these cases are not very common and printing the first
one would be helpful enough, and we can add documentation
notes in ftrace to guide users.

>
> another example:
> enum {
>         BPF_LOCAL_STORAGE_GET_F_CREATE = 1,
>         BPF_SK_STORAGE_GET_F_CREATE = 1,
> };
>
> and another:
> enum {
>         BPF_SKB_TSTAMP_UNSPEC = 0,
>         BPF_SKB_TSTAMP_DELIVERY_MONO = 1,
>         BPF_SKB_CLOCK_REALTIME = 0,
>         BPF_SKB_CLOCK_MONOTONIC = 1,
>         BPF_SKB_CLOCK_TAI = 2,
> };
>
> I'd rather not print any and keep it integer only.
>
> pw-bot: cr

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-04 14:52             ` Donglin Peng
@ 2026-02-05  9:21               ` Donglin Peng
  2026-02-05 15:56                 ` Alexei Starovoitov
  2026-02-05 18:04               ` Steven Rostedt
  1 sibling, 1 reply; 23+ messages in thread
From: Donglin Peng @ 2026-02-05  9:21 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Steven Rostedt, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Wed, Feb 4, 2026 at 10:52 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> On Wed, Feb 4, 2026 at 12:00 AM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > >
> > > On Tue, 3 Feb 2026 21:50:47 +0800
> > > Donglin Peng <dolinux.peng@gmail.com> wrote:
> > >
> > > > Testing revealed that sorting within resolve_btfids introduces issues with
> > > > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > > > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > > > invoked by pahole. However, it means that we need a newer pahole
> > > > version.
> > >
> > > Sorting isn't a requirement just something I wanted to bring up. If it's
> > > too complex and doesn't achieve much benefit then let's not do it.
> > >
> > > My worry is because "cat trace" takes quite a long time just reading the
> > > BTF arguments. I'm worried it will just get worse with enums as well.
> > >
> > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > doing an extract and reading the trace.dat file is much faster than reading
> > > the trace file with arguments. I'll need to implement the enum logic too in
> > > libtraceevent.
> >
> > If you mean to do pretty printing of the trace in user space then +1 from me.
> >
> > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > Sorted BTF by name was ok, since it doesn't change original semantics.
> > While sorting enums by value gets us to the grey zone where
> > the sequence of enum names in vmlinux.h becomes different than in dwarf.
>
> Thanks, I agreed.
>
> >
> > Also id->name mapping in general is not precise.
> > There is no requirement for enums to be unique.
> > Just grabbing the first one:
> > ATA_PIO0 = 1,
> > ATA_PIO1 = 3,
> > ATA_PIO2 = 7,
> > ATA_UDMA0 = 1,
> > ATA_UDMA1 = 3,
> > ATA_UDMA2 = 7,
> > ATA_ID_CYLS = 1,
> > ATA_ID_HEADS = 3,
> > SCR_ERROR = 1,
> > SCR_CONTROL = 2,
> > SCR_ACTIVE = 3,
> >
> > All these names are part of the same enum type.
> > Which one to print? First one?

Another option is to print all matching entries, incurring increased
overhead and extended trace log length. However, I prefer printing
the first matching entry, though it might be inaccurate in rare cases.

>
> I think these cases are not very common and printing the first
> one would be helpful enough, and we can add documentation
> notes in ftrace to guide users.
>
> >
> > another example:
> > enum {
> >         BPF_LOCAL_STORAGE_GET_F_CREATE = 1,
> >         BPF_SK_STORAGE_GET_F_CREATE = 1,
> > };
> >
> > and another:
> > enum {
> >         BPF_SKB_TSTAMP_UNSPEC = 0,
> >         BPF_SKB_TSTAMP_DELIVERY_MONO = 1,
> >         BPF_SKB_CLOCK_REALTIME = 0,
> >         BPF_SKB_CLOCK_MONOTONIC = 1,
> >         BPF_SKB_CLOCK_TAI = 2,
> > };
> >
> > I'd rather not print any and keep it integer only.
> >
> > pw-bot: cr

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-05  9:21               ` Donglin Peng
@ 2026-02-05 15:56                 ` Alexei Starovoitov
  2026-02-06  4:09                   ` Donglin Peng
  0 siblings, 1 reply; 23+ messages in thread
From: Alexei Starovoitov @ 2026-02-05 15:56 UTC (permalink / raw)
  To: Donglin Peng
  Cc: Steven Rostedt, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Thu, Feb 5, 2026 at 1:21 AM Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> On Wed, Feb 4, 2026 at 10:52 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
> >
> > On Wed, Feb 4, 2026 at 12:00 AM Alexei Starovoitov
> > <alexei.starovoitov@gmail.com> wrote:
> > >
> > > On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > > >
> > > > On Tue, 3 Feb 2026 21:50:47 +0800
> > > > Donglin Peng <dolinux.peng@gmail.com> wrote:
> > > >
> > > > > Testing revealed that sorting within resolve_btfids introduces issues with
> > > > > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > > > > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > > > > invoked by pahole. However, it means that we need a newer pahole
> > > > > version.
> > > >
> > > > Sorting isn't a requirement just something I wanted to bring up. If it's
> > > > too complex and doesn't achieve much benefit then let's not do it.
> > > >
> > > > My worry is because "cat trace" takes quite a long time just reading the
> > > > BTF arguments. I'm worried it will just get worse with enums as well.
> > > >
> > > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > > doing an extract and reading the trace.dat file is much faster than reading
> > > > the trace file with arguments. I'll need to implement the enum logic too in
> > > > libtraceevent.
> > >
> > > If you mean to do pretty printing of the trace in user space then +1 from me.
> > >
> > > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > > Sorted BTF by name was ok, since it doesn't change original semantics.
> > > While sorting enums by value gets us to the grey zone where
> > > the sequence of enum names in vmlinux.h becomes different than in dwarf.
> >
> > Thanks, I agreed.
> >
> > >
> > > Also id->name mapping in general is not precise.
> > > There is no requirement for enums to be unique.
> > > Just grabbing the first one:
> > > ATA_PIO0 = 1,
> > > ATA_PIO1 = 3,
> > > ATA_PIO2 = 7,
> > > ATA_UDMA0 = 1,
> > > ATA_UDMA1 = 3,
> > > ATA_UDMA2 = 7,
> > > ATA_ID_CYLS = 1,
> > > ATA_ID_HEADS = 3,
> > > SCR_ERROR = 1,
> > > SCR_CONTROL = 2,
> > > SCR_ACTIVE = 3,
> > >
> > > All these names are part of the same enum type.
> > > Which one to print? First one?
>
> Another option is to print all matching entries, incurring increased
> overhead and extended trace log length. However, I prefer printing
> the first matching entry, though it might be inaccurate in rare cases.

I disagree. It's not rare.
I wouldn't print anything. Let user space deal with it.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-04 14:52             ` Donglin Peng
  2026-02-05  9:21               ` Donglin Peng
@ 2026-02-05 18:04               ` Steven Rostedt
  2026-02-06  4:04                 ` Donglin Peng
  2026-02-08 13:07                 ` Donglin Peng
  1 sibling, 2 replies; 23+ messages in thread
From: Steven Rostedt @ 2026-02-05 18:04 UTC (permalink / raw)
  To: Donglin Peng
  Cc: Alexei Starovoitov, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Wed, 4 Feb 2026 22:52:11 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > doing an extract and reading the trace.dat file is much faster than reading
> > > the trace file with arguments. I'll need to implement the enum logic too in
> > > libtraceevent.  
> >
> > If you mean to do pretty printing of the trace in user space then +1 from me.
> >
> > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > Sorted BTF by name was ok, since it doesn't change original semantics.
> > While sorting enums by value gets us to the grey zone where
> > the sequence of enum names in vmlinux.h becomes different than in dwarf.  
> 
> Thanks, I agreed.

BTW, I just officially released trace-cmd v3.4 (where you can see whats
new in that release here[1]).

The biggest change is that it saves the BTF file in the trace.dat file
and parses it on the report (it requires libtraceevent v1.9):

 ~# trace-cmd record -p function_graph -O funcgraph-args -g do_sys_openat2
 [..]
 ~# trace-cmd report
       trace-cmd-50935 [002] ...1.  3490.518138: funcgraph_entry:                   |  do_sys_openat2(dfd=4294967196, filename=0x557bb9e3ee10, how=0xffff88815220fea8) {
       trace-cmd-50935 [002] ...1.  3490.518141: funcgraph_entry:                   |    getname_flags(filename=0x557bb9e3ee10, flags=0) {
       trace-cmd-50935 [002] ...1.  3490.518142: funcgraph_entry:                   |      getname_flags.part.0(filename=0x557bb9e3ee10, flags=0) {
       trace-cmd-50935 [002] ...1.  3490.518143: funcgraph_entry:                   |        kmem_cache_alloc_noprof(s=0xffff888106c7e000, gfpflags=0xcc0) {
       trace-cmd-50935 [002] ...1.  3490.518145: funcgraph_entry:                   |          stack_trace_save(store=0xffff88815220fac8, size=0x40, skipnr=0x0) {
       trace-cmd-50935 [002] ...1.  3490.518147: funcgraph_entry:                   |            arch_stack_walk(consume_entry=0xffffffff94d9dfe0, cookie=0xffff88815220fa58, task=0xffff88812d4c3580, regs=0x0) {
       trace-cmd-50935 [002] ...1.  3490.518148: funcgraph_entry:                   |              __unwind_start(state=0xffff88815220f988, task=0xffff88812d4c3580, regs=0x0, first_frame=0xffff88815220fa28) {
       trace-cmd-50935 [002] ...1.  3490.518149: funcgraph_entry:        1.518 us   |                get_stack_info(stack=0xffff88815220f938, task=0xffff88812d4c3580, info=0xffff88815220f988, visit_mask=0xffff88815220f9a8); (ret=0x0)
       trace-cmd-50935 [002] ...1.  3490.518152: funcgraph_entry:                   |                unwind_next_frame(state=0xffff88815220f988) {
       trace-cmd-50935 [002] ...1.  3490.518153: funcgraph_entry:        0.951 us   |                  __rcu_read_lock(); (ret=0xffff88812d4c3580)

-- Steve



[1] https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/tag/?h=trace-cmd-v3.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-02 11:15 ` [PATCH 2/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
  2026-02-02 16:12   ` Steven Rostedt
@ 2026-02-06  0:12   ` Masami Hiramatsu
  1 sibling, 0 replies; 23+ messages in thread
From: Masami Hiramatsu @ 2026-02-06  0:12 UTC (permalink / raw)
  To: Donglin Peng
  Cc: rostedt, ast, mhiramat, andrii.nakryiko, linux-kernel,
	Donglin Peng, linux-trace-kernel

On Mon,  2 Feb 2026 19:15:48 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> From: Donglin Peng <pengdonglin@xiaomi.com>
> 
> Use BTF to print symbolic names for enum-type function arguments,
> improving trace readability.
> 
> Before:
> count_memcg_events(memcg=0xffff..., idx=20, count=0x1) {
> 
> After:
> count_memcg_events(memcg=0xffff..., idx=20 [PGFAULT], count=0x1) {

Hmm, it is interesting idea. Maybe I can also introduce the same
feature to fetcharg for fprobe/kprobes as a new type.
Since the enum type should be solved in parsing the event definition,
for fprobe/kprobes the performance will not be a performance problem.

Thanks,

> 
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Cc: Masami Hiramatsu <mhiramat@kernel.org>
> Cc: linux-trace-kernel@vger.kernel.org
> Signed-off-by: Donglin Peng <pengdonglin@xiaomi.com>
> ---
>  kernel/trace/trace_output.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
> index cc2d3306bb60..c395f768c3b8 100644
> --- a/kernel/trace/trace_output.c
> +++ b/kernel/trace/trace_output.c
> @@ -695,12 +695,13 @@ void print_function_args(struct trace_seq *s, unsigned long *args,
>  {
>  	const struct btf_param *param;
>  	const struct btf_type *t;
> +	const struct btf_enum *enump;
>  	const char *param_name;
>  	char name[KSYM_NAME_LEN];
>  	unsigned long arg;
>  	struct btf *btf;
>  	s32 tid, nr = 0;
> -	int a, p, x;
> +	int a, p, x, i;
>  	u16 encode;
>  
>  	trace_seq_printf(s, "(");
> @@ -754,6 +755,14 @@ void print_function_args(struct trace_seq *s, unsigned long *args,
>  			break;
>  		case BTF_KIND_ENUM:
>  			trace_seq_printf(s, "%ld", arg);
> +			for_each_enum(i, t, enump) {
> +				if (arg == enump->val) {
> +					trace_seq_printf(s, " [%s]",
> +							 btf_name_by_offset(btf,
> +							 enump->name_off));
> +					break;
> +				}
> +			}
>  			break;
>  		default:
>  			/* This does not handle complex arguments */
> -- 
> 2.34.1
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/2] btf: Add for_each_enum and for_each_enum64 helper macros
  2026-02-02 11:15 ` [PATCH 1/2] btf: Add for_each_enum and for_each_enum64 helper macros Donglin Peng
@ 2026-02-06  0:29   ` Masami Hiramatsu
  0 siblings, 0 replies; 23+ messages in thread
From: Masami Hiramatsu @ 2026-02-06  0:29 UTC (permalink / raw)
  To: Donglin Peng
  Cc: rostedt, ast, mhiramat, andrii.nakryiko, linux-kernel,
	Donglin Peng, Andrii Nakryiko, Eduard Zingerman, bpf

On Mon,  2 Feb 2026 19:15:47 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> From: Donglin Peng <pengdonglin@xiaomi.com>
> 
> Introduce two new helper macros, for_each_enum and for_each_enum64,
> to clean up code.
> 
> No functional changes.

This change looks good to me. But this should go through bpf tree.

Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Thanks,

> 
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Andrii Nakryiko <andrii@kernel.org>
> Cc: Eduard Zingerman <eddyz87@gmail.com>
> Cc: bpf@vger.kernel.org
> Signed-off-by: Donglin Peng <pengdonglin@xiaomi.com>
> ---
>  include/linux/btf.h | 10 +++++++
>  kernel/bpf/btf.c    | 66 +++++++++++++++++++--------------------------
>  2 files changed, 38 insertions(+), 38 deletions(-)
> 
> diff --git a/include/linux/btf.h b/include/linux/btf.h
> index f06976ffb63f..cde2deb8e25e 100644
> --- a/include/linux/btf.h
> +++ b/include/linux/btf.h
> @@ -254,6 +254,16 @@ const char *btf_type_str(const struct btf_type *t);
>  	     i < btf_type_vlen(datasec_type);			\
>  	     i++, member++)
>  
> +#define for_each_enum(i, enum_type, member)			\
> +	for (i = 0, member = btf_enum(enum_type);		\
> +	     i < btf_type_vlen(enum_type);			\
> +	     i++, member++)
> +
> +#define for_each_enum64(i, enum_type, member)			\
> +	for (i = 0, member = btf_enum64(enum_type);		\
> +	     i < btf_type_vlen(enum_type);			\
> +	     i++, member++)
> +
>  static inline bool btf_type_is_ptr(const struct btf_type *t)
>  {
>  	return BTF_INFO_KIND(t->info) == BTF_KIND_PTR;
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 0de8fc8a0e0b..c80a7a0cbe1d 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -728,11 +728,6 @@ static const struct btf_array *btf_type_array(const struct btf_type *t)
>  	return (const struct btf_array *)(t + 1);
>  }
>  
> -static const struct btf_enum *btf_type_enum(const struct btf_type *t)
> -{
> -	return (const struct btf_enum *)(t + 1);
> -}
> -
>  static const struct btf_var *btf_type_var(const struct btf_type *t)
>  {
>  	return (const struct btf_var *)(t + 1);
> @@ -743,11 +738,6 @@ static const struct btf_decl_tag *btf_type_decl_tag(const struct btf_type *t)
>  	return (const struct btf_decl_tag *)(t + 1);
>  }
>  
> -static const struct btf_enum64 *btf_type_enum64(const struct btf_type *t)
> -{
> -	return (const struct btf_enum64 *)(t + 1);
> -}
> -
>  static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t)
>  {
>  	return kind_ops[BTF_INFO_KIND(t->info)];
> @@ -4317,14 +4307,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
>  			       const struct btf_type *t,
>  			       u32 meta_left)
>  {
> -	const struct btf_enum *enums = btf_type_enum(t);
> +	const struct btf_enum *enump;
>  	struct btf *btf = env->btf;
>  	const char *fmt_str;
>  	u16 i, nr_enums;
>  	u32 meta_needed;
>  
>  	nr_enums = btf_type_vlen(t);
> -	meta_needed = nr_enums * sizeof(*enums);
> +	meta_needed = nr_enums * sizeof(*enump);
>  
>  	if (meta_left < meta_needed) {
>  		btf_verifier_log_basic(env, t,
> @@ -4347,16 +4337,16 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
>  
>  	btf_verifier_log_type(env, t, NULL);
>  
> -	for (i = 0; i < nr_enums; i++) {
> -		if (!btf_name_offset_valid(btf, enums[i].name_off)) {
> +	for_each_enum(i, t, enump) {
> +		if (!btf_name_offset_valid(btf, enump->name_off)) {
>  			btf_verifier_log(env, "\tInvalid name_offset:%u",
> -					 enums[i].name_off);
> +					 enump->name_off);
>  			return -EINVAL;
>  		}
>  
>  		/* enum member must have a valid name */
> -		if (!enums[i].name_off ||
> -		    !btf_name_valid_identifier(btf, enums[i].name_off)) {
> +		if (!enump->name_off ||
> +		    !btf_name_valid_identifier(btf, enump->name_off)) {
>  			btf_verifier_log_type(env, t, "Invalid name");
>  			return -EINVAL;
>  		}
> @@ -4365,8 +4355,8 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
>  			continue;
>  		fmt_str = btf_type_kflag(t) ? "\t%s val=%d\n" : "\t%s val=%u\n";
>  		btf_verifier_log(env, fmt_str,
> -				 __btf_name_by_offset(btf, enums[i].name_off),
> -				 enums[i].val);
> +				 __btf_name_by_offset(btf, enump->name_off),
> +				 enump->val);
>  	}
>  
>  	return meta_needed;
> @@ -4382,8 +4372,8 @@ static void btf_enum_show(const struct btf *btf, const struct btf_type *t,
>  			  u32 type_id, void *data, u8 bits_offset,
>  			  struct btf_show *show)
>  {
> -	const struct btf_enum *enums = btf_type_enum(t);
> -	u32 i, nr_enums = btf_type_vlen(t);
> +	const struct btf_enum *enump;
> +	u32 i;
>  	void *safe_data;
>  	int v;
>  
> @@ -4393,13 +4383,13 @@ static void btf_enum_show(const struct btf *btf, const struct btf_type *t,
>  
>  	v = *(int *)safe_data;
>  
> -	for (i = 0; i < nr_enums; i++) {
> -		if (v != enums[i].val)
> +	for_each_enum(i, t, enump) {
> +		if (v != enump->val)
>  			continue;
>  
>  		btf_show_type_value(show, "%s",
>  				    __btf_name_by_offset(btf,
> -							 enums[i].name_off));
> +							 enump->name_off));
>  
>  		btf_show_end_type(show);
>  		return;
> @@ -4425,14 +4415,14 @@ static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
>  				 const struct btf_type *t,
>  				 u32 meta_left)
>  {
> -	const struct btf_enum64 *enums = btf_type_enum64(t);
> +	const struct btf_enum64 *enump;
>  	struct btf *btf = env->btf;
>  	const char *fmt_str;
>  	u16 i, nr_enums;
>  	u32 meta_needed;
>  
>  	nr_enums = btf_type_vlen(t);
> -	meta_needed = nr_enums * sizeof(*enums);
> +	meta_needed = nr_enums * sizeof(*enump);
>  
>  	if (meta_left < meta_needed) {
>  		btf_verifier_log_basic(env, t,
> @@ -4455,16 +4445,16 @@ static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
>  
>  	btf_verifier_log_type(env, t, NULL);
>  
> -	for (i = 0; i < nr_enums; i++) {
> -		if (!btf_name_offset_valid(btf, enums[i].name_off)) {
> +	for_each_enum64(i, t, enump) {
> +		if (!btf_name_offset_valid(btf, enump->name_off)) {
>  			btf_verifier_log(env, "\tInvalid name_offset:%u",
> -					 enums[i].name_off);
> +					 enump->name_off);
>  			return -EINVAL;
>  		}
>  
>  		/* enum member must have a valid name */
> -		if (!enums[i].name_off ||
> -		    !btf_name_valid_identifier(btf, enums[i].name_off)) {
> +		if (!enump->name_off ||
> +		    !btf_name_valid_identifier(btf, enump->name_off)) {
>  			btf_verifier_log_type(env, t, "Invalid name");
>  			return -EINVAL;
>  		}
> @@ -4474,8 +4464,8 @@ static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
>  
>  		fmt_str = btf_type_kflag(t) ? "\t%s val=%lld\n" : "\t%s val=%llu\n";
>  		btf_verifier_log(env, fmt_str,
> -				 __btf_name_by_offset(btf, enums[i].name_off),
> -				 btf_enum64_value(enums + i));
> +				 __btf_name_by_offset(btf, enump->name_off),
> +				 btf_enum64_value(enump));
>  	}
>  
>  	return meta_needed;
> @@ -4485,8 +4475,8 @@ static void btf_enum64_show(const struct btf *btf, const struct btf_type *t,
>  			    u32 type_id, void *data, u8 bits_offset,
>  			    struct btf_show *show)
>  {
> -	const struct btf_enum64 *enums = btf_type_enum64(t);
> -	u32 i, nr_enums = btf_type_vlen(t);
> +	const struct btf_enum64 *enump;
> +	u32 i;
>  	void *safe_data;
>  	s64 v;
>  
> @@ -4496,13 +4486,13 @@ static void btf_enum64_show(const struct btf *btf, const struct btf_type *t,
>  
>  	v = *(u64 *)safe_data;
>  
> -	for (i = 0; i < nr_enums; i++) {
> -		if (v != btf_enum64_value(enums + i))
> +	for_each_enum64(i, t, enump) {
> +		if (v != btf_enum64_value(enump))
>  			continue;
>  
>  		btf_show_type_value(show, "%s",
>  				    __btf_name_by_offset(btf,
> -							 enums[i].name_off));
> +							 enump->name_off));
>  
>  		btf_show_end_type(show);
>  		return;
> -- 
> 2.34.1
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-05 18:04               ` Steven Rostedt
@ 2026-02-06  4:04                 ` Donglin Peng
  2026-02-08 13:07                 ` Donglin Peng
  1 sibling, 0 replies; 23+ messages in thread
From: Donglin Peng @ 2026-02-06  4:04 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Alexei Starovoitov, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Fri, Feb 6, 2026 at 2:05 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Wed, 4 Feb 2026 22:52:11 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> > > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > > doing an extract and reading the trace.dat file is much faster than reading
> > > > the trace file with arguments. I'll need to implement the enum logic too in
> > > > libtraceevent.
> > >
> > > If you mean to do pretty printing of the trace in user space then +1 from me.
> > >
> > > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > > Sorted BTF by name was ok, since it doesn't change original semantics.
> > > While sorting enums by value gets us to the grey zone where
> > > the sequence of enum names in vmlinux.h becomes different than in dwarf.
> >
> > Thanks, I agreed.
>
> BTW, I just officially released trace-cmd v3.4 (where you can see whats
> new in that release here[1]).
>
> The biggest change is that it saves the BTF file in the trace.dat file
> and parses it on the report (it requires libtraceevent v1.9):
>
>  ~# trace-cmd record -p function_graph -O funcgraph-args -g do_sys_openat2
>  [..]
>  ~# trace-cmd report
>        trace-cmd-50935 [002] ...1.  3490.518138: funcgraph_entry:                   |  do_sys_openat2(dfd=4294967196, filename=0x557bb9e3ee10, how=0xffff88815220fea8) {
>        trace-cmd-50935 [002] ...1.  3490.518141: funcgraph_entry:                   |    getname_flags(filename=0x557bb9e3ee10, flags=0) {
>        trace-cmd-50935 [002] ...1.  3490.518142: funcgraph_entry:                   |      getname_flags.part.0(filename=0x557bb9e3ee10, flags=0) {
>        trace-cmd-50935 [002] ...1.  3490.518143: funcgraph_entry:                   |        kmem_cache_alloc_noprof(s=0xffff888106c7e000, gfpflags=0xcc0) {
>        trace-cmd-50935 [002] ...1.  3490.518145: funcgraph_entry:                   |          stack_trace_save(store=0xffff88815220fac8, size=0x40, skipnr=0x0) {
>        trace-cmd-50935 [002] ...1.  3490.518147: funcgraph_entry:                   |            arch_stack_walk(consume_entry=0xffffffff94d9dfe0, cookie=0xffff88815220fa58, task=0xffff88812d4c3580, regs=0x0) {
>        trace-cmd-50935 [002] ...1.  3490.518148: funcgraph_entry:                   |              __unwind_start(state=0xffff88815220f988, task=0xffff88812d4c3580, regs=0x0, first_frame=0xffff88815220fa28) {
>        trace-cmd-50935 [002] ...1.  3490.518149: funcgraph_entry:        1.518 us   |                get_stack_info(stack=0xffff88815220f938, task=0xffff88812d4c3580, info=0xffff88815220f988, visit_mask=0xffff88815220f9a8); (ret=0x0)
>        trace-cmd-50935 [002] ...1.  3490.518152: funcgraph_entry:                   |                unwind_next_frame(state=0xffff88815220f988) {
>        trace-cmd-50935 [002] ...1.  3490.518153: funcgraph_entry:        0.951 us   |                  __rcu_read_lock(); (ret=0xffff88812d4c3580)

Thanks, I will implement this feature in libtraceevent.

>
> -- Steve
>
>
>
> [1] https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/tag/?h=trace-cmd-v3.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-05 15:56                 ` Alexei Starovoitov
@ 2026-02-06  4:09                   ` Donglin Peng
  2026-02-06 16:04                     ` Alexei Starovoitov
  0 siblings, 1 reply; 23+ messages in thread
From: Donglin Peng @ 2026-02-06  4:09 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Steven Rostedt, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Thu, Feb 5, 2026 at 11:56 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Thu, Feb 5, 2026 at 1:21 AM Donglin Peng <dolinux.peng@gmail.com> wrote:
> >
> > On Wed, Feb 4, 2026 at 10:52 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
> > >
> > > On Wed, Feb 4, 2026 at 12:00 AM Alexei Starovoitov
> > > <alexei.starovoitov@gmail.com> wrote:
> > > >
> > > > On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > > > >
> > > > > On Tue, 3 Feb 2026 21:50:47 +0800
> > > > > Donglin Peng <dolinux.peng@gmail.com> wrote:
> > > > >
> > > > > > Testing revealed that sorting within resolve_btfids introduces issues with
> > > > > > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > > > > > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > > > > > invoked by pahole. However, it means that we need a newer pahole
> > > > > > version.
> > > > >
> > > > > Sorting isn't a requirement just something I wanted to bring up. If it's
> > > > > too complex and doesn't achieve much benefit then let's not do it.
> > > > >
> > > > > My worry is because "cat trace" takes quite a long time just reading the
> > > > > BTF arguments. I'm worried it will just get worse with enums as well.
> > > > >
> > > > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > > > doing an extract and reading the trace.dat file is much faster than reading
> > > > > the trace file with arguments. I'll need to implement the enum logic too in
> > > > > libtraceevent.
> > > >
> > > > If you mean to do pretty printing of the trace in user space then +1 from me.
> > > >
> > > > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > > > Sorted BTF by name was ok, since it doesn't change original semantics.
> > > > While sorting enums by value gets us to the grey zone where
> > > > the sequence of enum names in vmlinux.h becomes different than in dwarf.
> > >
> > > Thanks, I agreed.
> > >
> > > >
> > > > Also id->name mapping in general is not precise.
> > > > There is no requirement for enums to be unique.
> > > > Just grabbing the first one:
> > > > ATA_PIO0 = 1,
> > > > ATA_PIO1 = 3,
> > > > ATA_PIO2 = 7,
> > > > ATA_UDMA0 = 1,
> > > > ATA_UDMA1 = 3,
> > > > ATA_UDMA2 = 7,
> > > > ATA_ID_CYLS = 1,
> > > > ATA_ID_HEADS = 3,
> > > > SCR_ERROR = 1,
> > > > SCR_CONTROL = 2,
> > > > SCR_ACTIVE = 3,
> > > >
> > > > All these names are part of the same enum type.
> > > > Which one to print? First one?
> >
> > Another option is to print all matching entries, incurring increased
> > overhead and extended trace log length. However, I prefer printing
> > the first matching entry, though it might be inaccurate in rare cases.
>
> I disagree. It's not rare.
> I wouldn't print anything. Let user space deal with it.

Okay, I will implement this in libtraceevent first. By the way, would the first
patch [1] introducing the for_each_enumand for_each_enum64 helper
macros be acceptable?

[1] https://lore.kernel.org/lkml/20260202111548.3555306-2-dolinux.peng@gmail.com/

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-06  4:09                   ` Donglin Peng
@ 2026-02-06 16:04                     ` Alexei Starovoitov
  2026-02-08 13:08                       ` Donglin Peng
  0 siblings, 1 reply; 23+ messages in thread
From: Alexei Starovoitov @ 2026-02-06 16:04 UTC (permalink / raw)
  To: Donglin Peng
  Cc: Steven Rostedt, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Thu, Feb 5, 2026 at 8:10 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> On Thu, Feb 5, 2026 at 11:56 PM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > On Thu, Feb 5, 2026 at 1:21 AM Donglin Peng <dolinux.peng@gmail.com> wrote:
> > >
> > > On Wed, Feb 4, 2026 at 10:52 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
> > > >
> > > > On Wed, Feb 4, 2026 at 12:00 AM Alexei Starovoitov
> > > > <alexei.starovoitov@gmail.com> wrote:
> > > > >
> > > > > On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > > > > >
> > > > > > On Tue, 3 Feb 2026 21:50:47 +0800
> > > > > > Donglin Peng <dolinux.peng@gmail.com> wrote:
> > > > > >
> > > > > > > Testing revealed that sorting within resolve_btfids introduces issues with
> > > > > > > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > > > > > > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > > > > > > invoked by pahole. However, it means that we need a newer pahole
> > > > > > > version.
> > > > > >
> > > > > > Sorting isn't a requirement just something I wanted to bring up. If it's
> > > > > > too complex and doesn't achieve much benefit then let's not do it.
> > > > > >
> > > > > > My worry is because "cat trace" takes quite a long time just reading the
> > > > > > BTF arguments. I'm worried it will just get worse with enums as well.
> > > > > >
> > > > > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > > > > doing an extract and reading the trace.dat file is much faster than reading
> > > > > > the trace file with arguments. I'll need to implement the enum logic too in
> > > > > > libtraceevent.
> > > > >
> > > > > If you mean to do pretty printing of the trace in user space then +1 from me.
> > > > >
> > > > > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > > > > Sorted BTF by name was ok, since it doesn't change original semantics.
> > > > > While sorting enums by value gets us to the grey zone where
> > > > > the sequence of enum names in vmlinux.h becomes different than in dwarf.
> > > >
> > > > Thanks, I agreed.
> > > >
> > > > >
> > > > > Also id->name mapping in general is not precise.
> > > > > There is no requirement for enums to be unique.
> > > > > Just grabbing the first one:
> > > > > ATA_PIO0 = 1,
> > > > > ATA_PIO1 = 3,
> > > > > ATA_PIO2 = 7,
> > > > > ATA_UDMA0 = 1,
> > > > > ATA_UDMA1 = 3,
> > > > > ATA_UDMA2 = 7,
> > > > > ATA_ID_CYLS = 1,
> > > > > ATA_ID_HEADS = 3,
> > > > > SCR_ERROR = 1,
> > > > > SCR_CONTROL = 2,
> > > > > SCR_ACTIVE = 3,
> > > > >
> > > > > All these names are part of the same enum type.
> > > > > Which one to print? First one?
> > >
> > > Another option is to print all matching entries, incurring increased
> > > overhead and extended trace log length. However, I prefer printing
> > > the first matching entry, though it might be inaccurate in rare cases.
> >
> > I disagree. It's not rare.
> > I wouldn't print anything. Let user space deal with it.
>
> Okay, I will implement this in libtraceevent first. By the way, would the first
> patch [1] introducing the for_each_enumand for_each_enum64 helper
> macros be acceptable?
>
> [1] https://lore.kernel.org/lkml/20260202111548.3555306-2-dolinux.peng@gmail.com/

Just that patch alone? What's the point?
Refactor for what? Does it read better? No.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-05 18:04               ` Steven Rostedt
  2026-02-06  4:04                 ` Donglin Peng
@ 2026-02-08 13:07                 ` Donglin Peng
  2026-02-08 15:27                   ` Steven Rostedt
  1 sibling, 1 reply; 23+ messages in thread
From: Donglin Peng @ 2026-02-08 13:07 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Alexei Starovoitov, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Fri, Feb 6, 2026 at 2:05 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Wed, 4 Feb 2026 22:52:11 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> > > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > > doing an extract and reading the trace.dat file is much faster than reading
> > > > the trace file with arguments. I'll need to implement the enum logic too in
> > > > libtraceevent.
> > >
> > > If you mean to do pretty printing of the trace in user space then +1 from me.
> > >
> > > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > > Sorted BTF by name was ok, since it doesn't change original semantics.
> > > While sorting enums by value gets us to the grey zone where
> > > the sequence of enum names in vmlinux.h becomes different than in dwarf.
> >
> > Thanks, I agreed.
>
> BTW, I just officially released trace-cmd v3.4 (where you can see whats
> new in that release here[1]).
>
> The biggest change is that it saves the BTF file in the trace.dat file
> and parses it on the report (it requires libtraceevent v1.9):
>
>  ~# trace-cmd record -p function_graph -O funcgraph-args -g do_sys_openat2
>  [..]
>  ~# trace-cmd report
>        trace-cmd-50935 [002] ...1.  3490.518138: funcgraph_entry:                   |  do_sys_openat2(dfd=4294967196, filename=0x557bb9e3ee10, how=0xffff88815220fea8) {
>        trace-cmd-50935 [002] ...1.  3490.518141: funcgraph_entry:                   |    getname_flags(filename=0x557bb9e3ee10, flags=0) {
>        trace-cmd-50935 [002] ...1.  3490.518142: funcgraph_entry:                   |      getname_flags.part.0(filename=0x557bb9e3ee10, flags=0) {
>        trace-cmd-50935 [002] ...1.  3490.518143: funcgraph_entry:                   |        kmem_cache_alloc_noprof(s=0xffff888106c7e000, gfpflags=0xcc0) {
>        trace-cmd-50935 [002] ...1.  3490.518145: funcgraph_entry:                   |          stack_trace_save(store=0xffff88815220fac8, size=0x40, skipnr=0x0) {
>        trace-cmd-50935 [002] ...1.  3490.518147: funcgraph_entry:                   |            arch_stack_walk(consume_entry=0xffffffff94d9dfe0, cookie=0xffff88815220fa58, task=0xffff88812d4c3580, regs=0x0) {
>        trace-cmd-50935 [002] ...1.  3490.518148: funcgraph_entry:                   |              __unwind_start(state=0xffff88815220f988, task=0xffff88812d4c3580, regs=0x0, first_frame=0xffff88815220fa28) {
>        trace-cmd-50935 [002] ...1.  3490.518149: funcgraph_entry:        1.518 us   |                get_stack_info(stack=0xffff88815220f938, task=0xffff88812d4c3580, info=0xffff88815220f988, visit_mask=0xffff88815220f9a8); (ret=0x0)
>        trace-cmd-50935 [002] ...1.  3490.518152: funcgraph_entry:                   |                unwind_next_frame(state=0xffff88815220f988) {
>        trace-cmd-50935 [002] ...1.  3490.518153: funcgraph_entry:        0.951 us   |                  __rcu_read_lock(); (ret=0xffff88812d4c3580)

Hi Steve,

I noticed that trace-cmd 3.4 introduced a new feature:

- Add support for showing parent functions in function graph

  If the "funcgraph-retaddr" option is set during function graph tracing,
  the parent functions will now be displayed:

  preempt_count_add(val=65536); /* <-irq_enter_rcu */ (ret=0x10001)

However, it currently only prints the caller's entry point. I suggest
enhancing this to include the **offset within the caller** as well. This
would allow tools like `faddr2line` to locate the exact call site accurately.

I implemented a tool named FuncGraph[1] to convert function_graph
ftrace output into an interactive HTML file. It leverages fastfaddr2line
to map return addresses (e.g., __sys_bpf+0x51/0x500) to their
corresponding call sites, such as: __sys_bpfat kernel/bpf/syscall.c:6115.

What do you think?

Thanks,
Donglin

[1] https://github.com/pengdonglin137/FuncGraph

>
> -- Steve
>
>
>
> [1] https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/tag/?h=trace-cmd-v3.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-06 16:04                     ` Alexei Starovoitov
@ 2026-02-08 13:08                       ` Donglin Peng
  0 siblings, 0 replies; 23+ messages in thread
From: Donglin Peng @ 2026-02-08 13:08 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Steven Rostedt, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Sat, Feb 7, 2026 at 12:05 AM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Thu, Feb 5, 2026 at 8:10 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
> >
> > On Thu, Feb 5, 2026 at 11:56 PM Alexei Starovoitov
> > <alexei.starovoitov@gmail.com> wrote:
> > >
> > > On Thu, Feb 5, 2026 at 1:21 AM Donglin Peng <dolinux.peng@gmail.com> wrote:
> > > >
> > > > On Wed, Feb 4, 2026 at 10:52 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
> > > > >
> > > > > On Wed, Feb 4, 2026 at 12:00 AM Alexei Starovoitov
> > > > > <alexei.starovoitov@gmail.com> wrote:
> > > > > >
> > > > > > On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > > > > > >
> > > > > > > On Tue, 3 Feb 2026 21:50:47 +0800
> > > > > > > Donglin Peng <dolinux.peng@gmail.com> wrote:
> > > > > > >
> > > > > > > > Testing revealed that sorting within resolve_btfids introduces issues with
> > > > > > > > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > > > > > > > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > > > > > > > invoked by pahole. However, it means that we need a newer pahole
> > > > > > > > version.
> > > > > > >
> > > > > > > Sorting isn't a requirement just something I wanted to bring up. If it's
> > > > > > > too complex and doesn't achieve much benefit then let's not do it.
> > > > > > >
> > > > > > > My worry is because "cat trace" takes quite a long time just reading the
> > > > > > > BTF arguments. I'm worried it will just get worse with enums as well.
> > > > > > >
> > > > > > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > > > > > doing an extract and reading the trace.dat file is much faster than reading
> > > > > > > the trace file with arguments. I'll need to implement the enum logic too in
> > > > > > > libtraceevent.
> > > > > >
> > > > > > If you mean to do pretty printing of the trace in user space then +1 from me.
> > > > > >
> > > > > > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > > > > > Sorted BTF by name was ok, since it doesn't change original semantics.
> > > > > > While sorting enums by value gets us to the grey zone where
> > > > > > the sequence of enum names in vmlinux.h becomes different than in dwarf.
> > > > >
> > > > > Thanks, I agreed.
> > > > >
> > > > > >
> > > > > > Also id->name mapping in general is not precise.
> > > > > > There is no requirement for enums to be unique.
> > > > > > Just grabbing the first one:
> > > > > > ATA_PIO0 = 1,
> > > > > > ATA_PIO1 = 3,
> > > > > > ATA_PIO2 = 7,
> > > > > > ATA_UDMA0 = 1,
> > > > > > ATA_UDMA1 = 3,
> > > > > > ATA_UDMA2 = 7,
> > > > > > ATA_ID_CYLS = 1,
> > > > > > ATA_ID_HEADS = 3,
> > > > > > SCR_ERROR = 1,
> > > > > > SCR_CONTROL = 2,
> > > > > > SCR_ACTIVE = 3,
> > > > > >
> > > > > > All these names are part of the same enum type.
> > > > > > Which one to print? First one?
> > > >
> > > > Another option is to print all matching entries, incurring increased
> > > > overhead and extended trace log length. However, I prefer printing
> > > > the first matching entry, though it might be inaccurate in rare cases.
> > >
> > > I disagree. It's not rare.
> > > I wouldn't print anything. Let user space deal with it.
> >
> > Okay, I will implement this in libtraceevent first. By the way, would the first
> > patch [1] introducing the for_each_enumand for_each_enum64 helper
> > macros be acceptable?
> >
> > [1] https://lore.kernel.org/lkml/20260202111548.3555306-2-dolinux.peng@gmail.com/
>
> Just that patch alone? What's the point?
> Refactor for what? Does it read better? No.

Thanks, I see.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-08 13:07                 ` Donglin Peng
@ 2026-02-08 15:27                   ` Steven Rostedt
  2026-02-08 15:42                     ` Donglin Peng
  0 siblings, 1 reply; 23+ messages in thread
From: Steven Rostedt @ 2026-02-08 15:27 UTC (permalink / raw)
  To: Donglin Peng
  Cc: Alexei Starovoitov, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Sun, 8 Feb 2026 21:07:37 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:
> Hi Steve,
> 
> I noticed that trace-cmd 3.4 introduced a new feature:
> 
> - Add support for showing parent functions in function graph
> 
>   If the "funcgraph-retaddr" option is set during function graph tracing,
>   the parent functions will now be displayed:
> 
>   preempt_count_add(val=65536); /* <-irq_enter_rcu */ (ret=0x10001)
> 
> However, it currently only prints the caller's entry point. I suggest
> enhancing this to include the **offset within the caller** as well. This
> would allow tools like `faddr2line` to locate the exact call site accurately.

Yeah, it makes sense to always show the offset of where it was called.
We can add that for 3.4.1.

> 
> I implemented a tool named FuncGraph[1] to convert function_graph
> ftrace output into an interactive HTML file. It leverages fastfaddr2line
> to map return addresses (e.g., __sys_bpf+0x51/0x500) to their
> corresponding call sites, such as: __sys_bpfat kernel/bpf/syscall.c:6115.
> 
> What do you think?

Sounds cool. Is this the vibe coding thing you talked about on Linked-In?

-- Steve

> 
> Thanks,
> Donglin
> 
> [1] https://github.com/pengdonglin137/FuncGraph
> 
> >
> > -- Steve
> >
> >
> >
> > [1] https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/tag/?h=trace-cmd-v3.4  


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-08 15:27                   ` Steven Rostedt
@ 2026-02-08 15:42                     ` Donglin Peng
  2026-02-08 16:47                       ` Steven Rostedt
  0 siblings, 1 reply; 23+ messages in thread
From: Donglin Peng @ 2026-02-08 15:42 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Alexei Starovoitov, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman

On Sun, Feb 8, 2026 at 11:27 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Sun, 8 Feb 2026 21:07:37 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
> > Hi Steve,
> >
> > I noticed that trace-cmd 3.4 introduced a new feature:
> >
> > - Add support for showing parent functions in function graph
> >
> >   If the "funcgraph-retaddr" option is set during function graph tracing,
> >   the parent functions will now be displayed:
> >
> >   preempt_count_add(val=65536); /* <-irq_enter_rcu */ (ret=0x10001)
> >
> > However, it currently only prints the caller's entry point. I suggest
> > enhancing this to include the **offset within the caller** as well. This
> > would allow tools like `faddr2line` to locate the exact call site accurately.
>
> Yeah, it makes sense to always show the offset of where it was called.
> We can add that for 3.4.1.

Thanks, I can send a patch to implement it.

>
> >
> > I implemented a tool named FuncGraph[1] to convert function_graph
> > ftrace output into an interactive HTML file. It leverages fastfaddr2line
> > to map return addresses (e.g., __sys_bpf+0x51/0x500) to their
> > corresponding call sites, such as: __sys_bpfat kernel/bpf/syscall.c:6115.
> >
> > What do you think?
>
> Sounds cool. Is this the vibe coding thing you talked about on Linked-In?

Yes. The project repository includes a sample HTML file (`sample.html`)
demonstrating the functionality — feel free to try it out.

I hope future versions of `trace-cmd` or `Kernelshark` could incorporate
similar features to enhance trace analysis workflows.

>
> -- Steve
>
> >
> > Thanks,
> > Donglin
> >
> > [1] https://github.com/pengdonglin137/FuncGraph
> >
> > >
> > > -- Steve
> > >
> > >
> > >
> > > [1] https://git.kernel.org/pub/scm/utils/trace-cmd/trace-cmd.git/tag/?h=trace-cmd-v3.4
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
  2026-02-08 15:42                     ` Donglin Peng
@ 2026-02-08 16:47                       ` Steven Rostedt
  0 siblings, 0 replies; 23+ messages in thread
From: Steven Rostedt @ 2026-02-08 16:47 UTC (permalink / raw)
  To: Donglin Peng
  Cc: Alexei Starovoitov, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman, Yordan Karadzhov

On Sun, 8 Feb 2026 23:42:50 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> I hope future versions of `trace-cmd` or `Kernelshark` could incorporate
> similar features to enhance trace analysis workflows.

Hey, they are both open source projects. Patches welcomed ;-)

Note, trace-cmd is mostly a side project for me. I mostly work on it in
my spare time (or in the plane while I travel). Which explains why it
doesn't get the loving it deserves.

KernelShark is now maintained by Yordan Karadzhov, which I believe he's
in the same predicament as I am. He too is open for patches.

-- Steve

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2026-02-08 16:48 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-02 11:15 [PATCH 0/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
2026-02-02 11:15 ` [PATCH 1/2] btf: Add for_each_enum and for_each_enum64 helper macros Donglin Peng
2026-02-06  0:29   ` Masami Hiramatsu
2026-02-02 11:15 ` [PATCH 2/2] tracing: resolve enum names for function arguments via BTF Donglin Peng
2026-02-02 16:12   ` Steven Rostedt
2026-02-03  2:17     ` Donglin Peng
2026-02-03 13:50       ` Donglin Peng
2026-02-03 15:17         ` Steven Rostedt
2026-02-03 16:00           ` Alexei Starovoitov
2026-02-04 14:52             ` Donglin Peng
2026-02-05  9:21               ` Donglin Peng
2026-02-05 15:56                 ` Alexei Starovoitov
2026-02-06  4:09                   ` Donglin Peng
2026-02-06 16:04                     ` Alexei Starovoitov
2026-02-08 13:08                       ` Donglin Peng
2026-02-05 18:04               ` Steven Rostedt
2026-02-06  4:04                 ` Donglin Peng
2026-02-08 13:07                 ` Donglin Peng
2026-02-08 15:27                   ` Steven Rostedt
2026-02-08 15:42                     ` Donglin Peng
2026-02-08 16:47                       ` Steven Rostedt
2026-02-04 14:16           ` Donglin Peng
2026-02-06  0:12   ` Masami Hiramatsu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox