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(-)
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
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 */
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 */
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>
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
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>
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
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
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>
© 2016 - 2026 Red Hat, Inc.