Skip to content

Commit aa316a7

Browse files
rostedtgregkh
authored andcommitted
fgraph: Copy args in intermediate storage with entry
[ Upstream commit e3d0197 ] The output of the function graph tracer has two ways to display its entries. One way for leaf functions with no events recorded within them, and the other is for functions with events recorded inside it. As function graph has an entry and exit event, to simplify the output of leaf functions it combines the two, where as non leaf functions are separate: 2) | invoke_rcu_core() { 2) | raise_softirq() { 2) 0.391 us | __raise_softirq_irqoff(); 2) 1.191 us | } 2) 2.086 us | } The __raise_softirq_irqoff() function above is really two events that were merged into one. Otherwise it would have looked like: 2) | invoke_rcu_core() { 2) | raise_softirq() { 2) | __raise_softirq_irqoff() { 2) 0.391 us | } 2) 1.191 us | } 2) 2.086 us | } In order to do this merge, the reading of the trace output file needs to look at the next event before printing. But since the pointer to the event is on the ring buffer, it needs to save the entry event before it looks at the next event as the next event goes out of focus as soon as a new event is read from the ring buffer. After it reads the next event, it will print the entry event with either the '{' (non leaf) or ';' and timestamps (leaf). The iterator used to read the trace file has storage for this event. The problem happens when the function graph tracer has arguments attached to the entry event as the entry now has a variable length "args" field. This field only gets set when funcargs option is used. But the args are not recorded in this temp data and garbage could be printed. The entry field is copied via: data->ent = *curr; Where "curr" is the entry field. But this method only saves the non variable length fields from the structure. Add a helper structure to the iterator data that adds the max args size to the data storage in the iterator. Then simply copy the entire entry into this storage (with size protection). Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Mark Rutland <mark.rutland@arm.com> Link: https://lore.kernel.org/20250820195522.51d4a268@gandalf.local.home Reported-by: Sasha Levin <sashal@kernel.org> Tested-by: Sasha Levin <sashal@kernel.org> Closes: https://lore.kernel.org/all/aJaxRVKverIjF4a6@lappy/ Fixes: ff5c9c5 ("ftrace: Add support for function argument to graph tracer") Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 10a5a83 commit aa316a7

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

kernel/trace/trace_functions_graph.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,21 @@ struct fgraph_cpu_data {
2727
unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH];
2828
};
2929

30+
struct fgraph_ent_args {
31+
struct ftrace_graph_ent_entry ent;
32+
/* Force the sizeof of args[] to have FTRACE_REGS_MAX_ARGS entries */
33+
unsigned long args[FTRACE_REGS_MAX_ARGS];
34+
};
35+
3036
struct fgraph_data {
3137
struct fgraph_cpu_data __percpu *cpu_data;
3238

3339
/* Place to preserve last processed entry. */
3440
union {
35-
struct ftrace_graph_ent_entry ent;
41+
struct fgraph_ent_args ent;
42+
/* TODO allow retaddr to have args */
3643
struct fgraph_retaddr_ent_entry rent;
37-
} ent;
44+
};
3845
struct ftrace_graph_ret_entry ret;
3946
int failed;
4047
int cpu;
@@ -627,10 +634,13 @@ get_return_for_leaf(struct trace_iterator *iter,
627634
* Save current and next entries for later reference
628635
* if the output fails.
629636
*/
630-
if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT))
631-
data->ent.rent = *(struct fgraph_retaddr_ent_entry *)curr;
632-
else
633-
data->ent.ent = *curr;
637+
if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT)) {
638+
data->rent = *(struct fgraph_retaddr_ent_entry *)curr;
639+
} else {
640+
int size = min((int)sizeof(data->ent), (int)iter->ent_size);
641+
642+
memcpy(&data->ent, curr, size);
643+
}
634644
/*
635645
* If the next event is not a return type, then
636646
* we only care about what type it is. Otherwise we can

0 commit comments

Comments
 (0)