[PATCH v5 0/3] Use BTF to trim return values

Donglin Peng posted 3 patches 3 weeks, 3 days ago
There is a newer version of this series
Documentation/trace/ftrace.rst       | 88 ++++++++++++++++------------
kernel/trace/Kconfig                 |  2 +-
kernel/trace/Makefile                |  2 +-
kernel/trace/trace_btf.c             | 68 +++++++++++++++++++++
kernel/trace/trace_btf.h             | 16 +++++
kernel/trace/trace_functions_graph.c | 50 ++++++++++++----
6 files changed, 173 insertions(+), 53 deletions(-)
[PATCH v5 0/3] Use BTF to trim return values
Posted by Donglin Peng 3 weeks, 3 days ago
From: pengdonglin <pengdonglin@xiaomi.com>

The funcgraph-retval option currently records one machine-word return
value without considering the function's declared return type. As a
result, void-returning functions can produce meaningless output, and
return values narrower than a general-purpose register can include
undefined high bits.

This series uses kernel BTF to identify the return type of traced
functions and to improve funcgraph-retval output:

  - Do not print a return value for functions with a void return type.
  - Trim integer, enum, struct, and union values to the available return
    value width when the BTF type provides suitable size information.
  - Format integer, enum, and boolean values according to their BTF
    encoding.
  - Mark values as "(trunc)" when the return type is wider than the
    value captured by the function graph tracer.

Here is an output comparison:

Before:
 # perf ftrace -G vfs_read --graph-opts retval
 ...
 1)               |   touch_atime() {
 1)               |     atime_needs_update() {
 1)   0.069 us    |       make_vfsuid(); /* ret=0x0 */
 1)   0.067 us    |       make_vfsgid(); /* ret=0x0 */
 1)               |       current_time() {
 1)   0.197 us    |         ktime_get_coarse_real_ts64_mg(); /* ret=0x187f886aec3ed6f5 */
 1)   0.352 us    |       } /* current_time ret=0x69380753 */
 1)   0.792 us    |     } /* atime_needs_update ret=0x0 */
 1)   0.937 us    |   } /* touch_atime ret=0x0 */

After:
 # perf ftrace -G vfs_read --graph-opts retval
 ...
 2)               |   touch_atime() {
 2)               |     atime_needs_update() {
 2)   0.070 us    |       make_vfsuid(); /* ret=0x0 */
 2)   0.070 us    |       make_vfsgid(); /* ret=0x0 */
 2)               |       current_time() {
 2)   0.162 us    |         ktime_get_coarse_real_ts64_mg();
 2)   0.312 us    |       } /* current_time ret=0x69380649(trunc) */
 2)   0.753 us    |     } /* atime_needs_update ret=false */
 2)   0.899 us    |   } /* touch_atime */

Changelog:

v5:
  - Add an inline fallback for btf_trim_retval() when
    CONFIG_DEBUG_INFO_BTF is disabled.
  - Release the BTF reference after return type lookup.

v4:
  - Link: https://lore.kernel.org/all/20251215034153.2367756-1-dolinux.peng@gmail.com/
  - Build trace_btf.c when CONFIG_DEBUG_INFO_BTF is enabled.
  - Remove the redundant BPF_SYSCALL dependency from
    CONFIG_PROBE_EVENTS_BTF_ARGS.
  - Update the funcgraph-retval documentation and cover letter.

v3:
  - Link: https://lore.kernel.org/all/20251209121349.525641-1-dolinux.peng@gmail.com/
  - Print the return value based on its type for human readability,
    thanks Masami.
  - Update the documentation and cover letter.

v2:
  - Link: https://lore.kernel.org/all/20251208131917.2444620-1-dolinux.peng@gmail.com/
  - Update the funcgraph-retval documentation.
  - Revise the cover letter.

v1:
  - Link: https://lore.kernel.org/all/20251207142742.229924-1-dolinux.peng@gmail.com/

pengdonglin (3):
  ftrace: Build trace_btf.c when CONFIG_DEBUG_INFO_BTF is enabled
  fgraph: Enhance funcgraph-retval with BTF-based type-aware output
  tracing: Update funcgraph-retval documentation

 Documentation/trace/ftrace.rst       | 88 ++++++++++++++++------------
 kernel/trace/Kconfig                 |  2 +-
 kernel/trace/Makefile                |  2 +-
 kernel/trace/trace_btf.c             | 68 +++++++++++++++++++++
 kernel/trace/trace_btf.h             | 16 +++++
 kernel/trace/trace_functions_graph.c | 50 ++++++++++++----
 6 files changed, 173 insertions(+), 53 deletions(-)

-- 
2.34.1
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Steven Rostedt 3 weeks, 3 days ago
On Tue,  1 Sep 2026 21:46:01 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> From: pengdonglin <pengdonglin@xiaomi.com>
> 
> The funcgraph-retval option currently records one machine-word return
> value without considering the function's declared return type. As a
> result, void-returning functions can produce meaningless output, and
> return values narrower than a general-purpose register can include
> undefined high bits.
> 
> This series uses kernel BTF to identify the return type of traced
> functions and to improve funcgraph-retval output:
> 
>   - Do not print a return value for functions with a void return type.
>   - Trim integer, enum, struct, and union values to the available return
>     value width when the BTF type provides suitable size information.
>   - Format integer, enum, and boolean values according to their BTF
>     encoding.
>   - Mark values as "(trunc)" when the return type is wider than the
>     value captured by the function graph tracer.

Hmm, I really don't like the "(trunc)" If it's the real return type, then
it should just print what the real size is. No need to state it was truncated.

-- Steve

> 
> Here is an output comparison:
> 
> Before:
>  # perf ftrace -G vfs_read --graph-opts retval
>  ...
>  1)               |   touch_atime() {
>  1)               |     atime_needs_update() {
>  1)   0.069 us    |       make_vfsuid(); /* ret=0x0 */
>  1)   0.067 us    |       make_vfsgid(); /* ret=0x0 */
>  1)               |       current_time() {
>  1)   0.197 us    |         ktime_get_coarse_real_ts64_mg(); /* ret=0x187f886aec3ed6f5 */
>  1)   0.352 us    |       } /* current_time ret=0x69380753 */
>  1)   0.792 us    |     } /* atime_needs_update ret=0x0 */
>  1)   0.937 us    |   } /* touch_atime ret=0x0 */
> 
> After:
>  # perf ftrace -G vfs_read --graph-opts retval
>  ...
>  2)               |   touch_atime() {
>  2)               |     atime_needs_update() {
>  2)   0.070 us    |       make_vfsuid(); /* ret=0x0 */
>  2)   0.070 us    |       make_vfsgid(); /* ret=0x0 */
>  2)               |       current_time() {
>  2)   0.162 us    |         ktime_get_coarse_real_ts64_mg();
>  2)   0.312 us    |       } /* current_time ret=0x69380649(trunc) */
>  2)   0.753 us    |     } /* atime_needs_update ret=false */
>  2)   0.899 us    |   } /* touch_atime */
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Peng Donglin 3 weeks, 3 days ago
On 9/2/26 01:57, Steven Rostedt wrote:
> On Tue,  1 Sep 2026 21:46:01 +0800
> Donglin Peng <dolinux.peng@gmail.com> wrote:
> 
>> From: pengdonglin <pengdonglin@xiaomi.com>
>>
>> The funcgraph-retval option currently records one machine-word return
>> value without considering the function's declared return type. As a
>> result, void-returning functions can produce meaningless output, and
>> return values narrower than a general-purpose register can include
>> undefined high bits.
>>
>> This series uses kernel BTF to identify the return type of traced
>> functions and to improve funcgraph-retval output:
>>
>>    - Do not print a return value for functions with a void return type.
>>    - Trim integer, enum, struct, and union values to the available return
>>      value width when the BTF type provides suitable size information.
>>    - Format integer, enum, and boolean values according to their BTF
>>      encoding.
>>    - Mark values as "(trunc)" when the return type is wider than the
>>      value captured by the function graph tracer.
> 
> Hmm, I really don't like the "(trunc)" If it's the real return type, then
> it should just print what the real size is. No need to state it was truncated.

Thanks, I agree. We can remove the "(trunc)" suffix and print the actual 
type information instead, for example:

     ret=0x5[struct:0x10]

This would indicate that the return type is a struct with a size of 0x10 
bytes.

Would this be acceptable?

> 
> -- Steve
> 
>>
>> Here is an output comparison:
>>
>> Before:
>>   # perf ftrace -G vfs_read --graph-opts retval
>>   ...
>>   1)               |   touch_atime() {
>>   1)               |     atime_needs_update() {
>>   1)   0.069 us    |       make_vfsuid(); /* ret=0x0 */
>>   1)   0.067 us    |       make_vfsgid(); /* ret=0x0 */
>>   1)               |       current_time() {
>>   1)   0.197 us    |         ktime_get_coarse_real_ts64_mg(); /* ret=0x187f886aec3ed6f5 */
>>   1)   0.352 us    |       } /* current_time ret=0x69380753 */
>>   1)   0.792 us    |     } /* atime_needs_update ret=0x0 */
>>   1)   0.937 us    |   } /* touch_atime ret=0x0 */
>>
>> After:
>>   # perf ftrace -G vfs_read --graph-opts retval
>>   ...
>>   2)               |   touch_atime() {
>>   2)               |     atime_needs_update() {
>>   2)   0.070 us    |       make_vfsuid(); /* ret=0x0 */
>>   2)   0.070 us    |       make_vfsgid(); /* ret=0x0 */
>>   2)               |       current_time() {
>>   2)   0.162 us    |         ktime_get_coarse_real_ts64_mg();
>>   2)   0.312 us    |       } /* current_time ret=0x69380649(trunc) */
>>   2)   0.753 us    |     } /* atime_needs_update ret=false */
>>   2)   0.899 us    |   } /* touch_atime */
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Masami Hiramatsu (Google) 3 weeks, 2 days ago
On Wed, 2 Sep 2026 11:25:29 +0800
Peng Donglin <dolinux.peng@gmail.com> wrote:

> >>    - Do not print a return value for functions with a void return type.
> >>    - Trim integer, enum, struct, and union values to the available return
> >>      value width when the BTF type provides suitable size information.
> >>    - Format integer, enum, and boolean values according to their BTF
> >>      encoding.
> >>    - Mark values as "(trunc)" when the return type is wider than the
> >>      value captured by the function graph tracer.
> > 
> > Hmm, I really don't like the "(trunc)" If it's the real return type, then
> > it should just print what the real size is. No need to state it was truncated.
> 
> Thanks, I agree. We can remove the "(trunc)" suffix and print the actual 
> type information instead, for example:
> 
>      ret=0x5[struct:0x10]
> 
> This would indicate that the return type is a struct with a size of 0x10 
> bytes.

Hmm, shouldn't both the actually applied size and the true size be displayed?
e.g.

ret=0x5 (in 8 bytes, true size: 16 bytes)

Thank you,

> 
> Would this be acceptable?
> 
> > 

-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Steven Rostedt 3 weeks, 1 day ago
On Wed, 2 Sep 2026 23:55:33 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:

> Hmm, shouldn't both the actually applied size and the true size be displayed?
> e.g.
> 
> ret=0x5 (in 8 bytes, true size: 16 bytes)

I have to ask. Why do we care? Is there a use for this information?

If not, ret=0x5 would be sufficient.

-- Steve
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Masami Hiramatsu (Google) 3 weeks, 1 day ago
On Thu, 3 Sep 2026 12:36:06 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> On Wed, 2 Sep 2026 23:55:33 +0900
> Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
> 
> > Hmm, shouldn't both the actually applied size and the true size be displayed?
> > e.g.
> > 
> > ret=0x5 (in 8 bytes, true size: 16 bytes)
> 
> I have to ask. Why do we care? Is there a use for this information?

If the structure itself is being returned, representing it as a scalar
value could lead to misunderstandings. Since we can check it is a
scalar or not, it should be noticed. In this meaning, I think "(trunc)"
is also good to me. (at least user can notice it)

Thanks,

> 
> If not, ret=0x5 would be sufficient.
> 
> -- Steve
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Steven Rostedt 3 weeks, 1 day ago
On Fri, 4 Sep 2026 08:48:08 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:

> > I have to ask. Why do we care? Is there a use for this information?  
> 
> If the structure itself is being returned, representing it as a scalar
> value could lead to misunderstandings. Since we can check it is a
> scalar or not, it should be noticed. In this meaning, I think "(trunc)"
> is also good to me. (at least user can notice it)

OK, after thinking about this more, I agree that "(trunc)" is the better option.

-- Steve
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Donglin Peng 3 weeks, 1 day ago
On Fri, Sep 4, 2026 at 8:30 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Fri, 4 Sep 2026 08:48:08 +0900
> Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
>
> > > I have to ask. Why do we care? Is there a use for this information?
> >
> > If the structure itself is being returned, representing it as a scalar
> > value could lead to misunderstandings. Since we can check it is a
> > scalar or not, it should be noticed. In this meaning, I think "(trunc)"
> > is also good to me. (at least user can notice it)
>
> OK, after thinking about this more, I agree that "(trunc)" is the better option.

Thanks, I will keep using "(trunc)" in v6.

>
> -- Steve
Re: [PATCH v5 0/3] Use BTF to trim return values
Posted by Donglin Peng 3 weeks, 1 day ago
On Wed, Sep 2, 2026 at 10:55 PM Masami Hiramatsu <mhiramat@kernel.org> wrote:
>
> On Wed, 2 Sep 2026 11:25:29 +0800
> Peng Donglin <dolinux.peng@gmail.com> wrote:
>
> > >>    - Do not print a return value for functions with a void return type.
> > >>    - Trim integer, enum, struct, and union values to the available return
> > >>      value width when the BTF type provides suitable size information.
> > >>    - Format integer, enum, and boolean values according to their BTF
> > >>      encoding.
> > >>    - Mark values as "(trunc)" when the return type is wider than the
> > >>      value captured by the function graph tracer.
> > >
> > > Hmm, I really don't like the "(trunc)" If it's the real return type, then
> > > it should just print what the real size is. No need to state it was truncated.
> >
> > Thanks, I agree. We can remove the "(trunc)" suffix and print the actual
> > type information instead, for example:
> >
> >      ret=0x5[struct:0x10]
> >
> > This would indicate that the return type is a struct with a size of 0x10
> > bytes.
>
> Hmm, shouldn't both the actually applied size and the true size be displayed?
> e.g.
>
> ret=0x5 (in 8 bytes, true size: 16 bytes)

Thanks, this is a good suggestion. To keep the trace concise, would this work?

  ret=0x5 (8/16B)

The suffix shows captured size and true BTF size, only when they differ.
WDYT?

>
> Thank you,
>
> >
> > Would this be acceptable?
> >
> > >
>
> --
> Masami Hiramatsu (Google) <mhiramat@kernel.org>