@@ -36,14 +36,19 @@ struct fgraph_ent_args {
3636 unsigned long args [FTRACE_REGS_MAX_ARGS ];
3737};
3838
39+ struct fgraph_retaddr_ent_args {
40+ struct fgraph_retaddr_ent_entry ent ;
41+ /* Force the sizeof of args[] to have FTRACE_REGS_MAX_ARGS entries */
42+ unsigned long args [FTRACE_REGS_MAX_ARGS ];
43+ };
44+
3945struct fgraph_data {
4046 struct fgraph_cpu_data __percpu * cpu_data ;
4147
4248 /* Place to preserve last processed entry. */
4349 union {
4450 struct fgraph_ent_args ent ;
45- /* TODO allow retaddr to have args */
46- struct fgraph_retaddr_ent_entry rent ;
51+ struct fgraph_retaddr_ent_args rent ;
4752 };
4853 struct ftrace_graph_ret_entry ret ;
4954 int failed ;
@@ -160,20 +165,32 @@ int __trace_graph_entry(struct trace_array *tr,
160165int __trace_graph_retaddr_entry (struct trace_array * tr ,
161166 struct ftrace_graph_ent * trace ,
162167 unsigned int trace_ctx ,
163- unsigned long retaddr )
168+ unsigned long retaddr ,
169+ struct ftrace_regs * fregs )
164170{
165171 struct ring_buffer_event * event ;
166172 struct trace_buffer * buffer = tr -> array_buffer .buffer ;
167173 struct fgraph_retaddr_ent_entry * entry ;
174+ int size ;
175+
176+ /* If fregs is defined, add FTRACE_REGS_MAX_ARGS long size words */
177+ size = sizeof (* entry ) + (FTRACE_REGS_MAX_ARGS * !!fregs * sizeof (long ));
168178
169179 event = trace_buffer_lock_reserve (buffer , TRACE_GRAPH_RETADDR_ENT ,
170- sizeof ( * entry ) , trace_ctx );
180+ size , trace_ctx );
171181 if (!event )
172182 return 0 ;
173183 entry = ring_buffer_event_data (event );
174- entry -> graph_ent .func = trace -> func ;
175- entry -> graph_ent .depth = trace -> depth ;
176- entry -> graph_ent .retaddr = retaddr ;
184+ entry -> graph_rent .ent = * trace ;
185+ entry -> graph_rent .retaddr = retaddr ;
186+
187+ #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
188+ if (fregs ) {
189+ for (int i = 0 ; i < FTRACE_REGS_MAX_ARGS ; i ++ )
190+ entry -> args [i ] = ftrace_regs_get_argument (fregs , i );
191+ }
192+ #endif
193+
177194 trace_buffer_unlock_commit_nostack (buffer , event );
178195
179196 return 1 ;
@@ -182,7 +199,8 @@ int __trace_graph_retaddr_entry(struct trace_array *tr,
182199int __trace_graph_retaddr_entry (struct trace_array * tr ,
183200 struct ftrace_graph_ent * trace ,
184201 unsigned int trace_ctx ,
185- unsigned long retaddr )
202+ unsigned long retaddr ,
203+ struct ftrace_regs * fregs )
186204{
187205 return 1 ;
188206}
@@ -267,7 +285,8 @@ static int graph_entry(struct ftrace_graph_ent *trace,
267285 if (IS_ENABLED (CONFIG_FUNCTION_GRAPH_RETADDR ) &&
268286 tracer_flags_is_set (tr , TRACE_GRAPH_PRINT_RETADDR )) {
269287 unsigned long retaddr = ftrace_graph_top_ret_addr (current );
270- ret = __trace_graph_retaddr_entry (tr , trace , trace_ctx , retaddr );
288+ ret = __trace_graph_retaddr_entry (tr , trace , trace_ctx ,
289+ retaddr , fregs );
271290 } else {
272291 ret = __graph_entry (tr , trace , trace_ctx , fregs );
273292 }
@@ -654,13 +673,9 @@ get_return_for_leaf(struct trace_iterator *iter,
654673 * Save current and next entries for later reference
655674 * if the output fails.
656675 */
657- if (unlikely (curr -> ent .type == TRACE_GRAPH_RETADDR_ENT )) {
658- data -> rent = * (struct fgraph_retaddr_ent_entry * )curr ;
659- } else {
660- int size = min ((int )sizeof (data -> ent ), (int )iter -> ent_size );
676+ int size = min_t (int , sizeof (data -> rent ), iter -> ent_size );
661677
662- memcpy (& data -> ent , curr , size );
663- }
678+ memcpy (& data -> rent , curr , size );
664679 /*
665680 * If the next event is not a return type, then
666681 * we only care about what type it is. Otherwise we can
@@ -838,7 +853,7 @@ static void print_graph_retaddr(struct trace_seq *s, struct fgraph_retaddr_ent_e
838853 trace_seq_puts (s , " /*" );
839854
840855 trace_seq_puts (s , " <-" );
841- seq_print_ip_sym_offset (s , entry -> graph_ent .retaddr , trace_flags );
856+ seq_print_ip_sym_offset (s , entry -> graph_rent .retaddr , trace_flags );
842857
843858 if (comment )
844859 trace_seq_puts (s , " */" );
@@ -984,7 +999,7 @@ print_graph_entry_leaf(struct trace_iterator *iter,
984999 trace_seq_printf (s , "%ps" , (void * )ret_func );
9851000
9861001 if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof (long )) {
987- print_function_args (s , entry -> args , ret_func );
1002+ print_function_args (s , FGRAPH_ENTRY_ARGS ( entry ) , ret_func );
9881003 trace_seq_putc (s , ';' );
9891004 } else
9901005 trace_seq_puts (s , "();" );
@@ -1036,7 +1051,7 @@ print_graph_entry_nested(struct trace_iterator *iter,
10361051 args_size = iter -> ent_size - offsetof(struct ftrace_graph_ent_entry , args );
10371052
10381053 if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof (long ))
1039- print_function_args (s , entry -> args , func );
1054+ print_function_args (s , FGRAPH_ENTRY_ARGS ( entry ) , func );
10401055 else
10411056 trace_seq_puts (s , "()" );
10421057
@@ -1218,11 +1233,14 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
12181233 /*
12191234 * print_graph_entry() may consume the current event,
12201235 * thus @field may become invalid, so we need to save it.
1221- * sizeof(struct ftrace_graph_ent_entry) is very small,
1222- * it can be safely saved at the stack.
1236+ * This function is shared by ftrace_graph_ent_entry and
1237+ * fgraph_retaddr_ent_entry, the size of the latter one
1238+ * is larger, but it is very small and can be safely saved
1239+ * at the stack.
12231240 */
12241241 struct ftrace_graph_ent_entry * entry ;
1225- u8 save_buf [sizeof (* entry ) + FTRACE_REGS_MAX_ARGS * sizeof (long )];
1242+ struct fgraph_retaddr_ent_entry * rentry ;
1243+ u8 save_buf [sizeof (* rentry ) + FTRACE_REGS_MAX_ARGS * sizeof (long )];
12261244
12271245 /* The ent_size is expected to be as big as the entry */
12281246 if (iter -> ent_size > sizeof (save_buf ))
@@ -1451,12 +1469,17 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags)
14511469 }
14521470#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
14531471 case TRACE_GRAPH_RETADDR_ENT : {
1454- struct fgraph_retaddr_ent_entry saved ;
1472+ /*
1473+ * ftrace_graph_ent_entry and fgraph_retaddr_ent_entry have
1474+ * similar functions and memory layouts. The only difference
1475+ * is that the latter one has an extra retaddr member, so
1476+ * they can share most of the logic.
1477+ */
14551478 struct fgraph_retaddr_ent_entry * rfield ;
14561479
14571480 trace_assign_type (rfield , entry );
1458- saved = * rfield ;
1459- return print_graph_entry (( struct ftrace_graph_ent_entry * ) & saved , s , iter , flags );
1481+ return print_graph_entry (( struct ftrace_graph_ent_entry * ) rfield ,
1482+ s , iter , flags );
14601483 }
14611484#endif
14621485 case TRACE_GRAPH_RET : {
0 commit comments