@@ -70,6 +70,10 @@ static struct tracer_opt trace_opts[] = {
7070#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
7171 /* Display function return address ? */
7272 { TRACER_OPT (funcgraph - retaddr , TRACE_GRAPH_PRINT_RETADDR ) },
73+ #endif
74+ #ifdef CONFIG_FUNCTION_TRACE_ARGS
75+ /* Display function arguments ? */
76+ { TRACER_OPT (funcgraph - args , TRACE_GRAPH_ARGS ) },
7377#endif
7478 /* Include sleep time (scheduled out) between entry and return */
7579 { TRACER_OPT (sleep - time , TRACE_GRAPH_SLEEP_TIME ) },
@@ -110,25 +114,43 @@ static void
110114print_graph_duration (struct trace_array * tr , unsigned long long duration ,
111115 struct trace_seq * s , u32 flags );
112116
113- int __trace_graph_entry (struct trace_array * tr ,
114- struct ftrace_graph_ent * trace ,
115- unsigned int trace_ctx )
117+ static int __graph_entry (struct trace_array * tr , struct ftrace_graph_ent * trace ,
118+ unsigned int trace_ctx , struct ftrace_regs * fregs )
116119{
117120 struct ring_buffer_event * event ;
118121 struct trace_buffer * buffer = tr -> array_buffer .buffer ;
119122 struct ftrace_graph_ent_entry * entry ;
123+ int size ;
120124
121- event = trace_buffer_lock_reserve (buffer , TRACE_GRAPH_ENT ,
122- sizeof (* entry ), trace_ctx );
125+ /* If fregs is defined, add FTRACE_REGS_MAX_ARGS long size words */
126+ size = sizeof (* entry ) + (FTRACE_REGS_MAX_ARGS * !!fregs * sizeof (long ));
127+
128+ event = trace_buffer_lock_reserve (buffer , TRACE_GRAPH_ENT , size , trace_ctx );
123129 if (!event )
124130 return 0 ;
125- entry = ring_buffer_event_data (event );
126- entry -> graph_ent = * trace ;
131+
132+ entry = ring_buffer_event_data (event );
133+ entry -> graph_ent = * trace ;
134+
135+ #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
136+ if (fregs ) {
137+ for (int i = 0 ; i < FTRACE_REGS_MAX_ARGS ; i ++ )
138+ entry -> args [i ] = ftrace_regs_get_argument (fregs , i );
139+ }
140+ #endif
141+
127142 trace_buffer_unlock_commit_nostack (buffer , event );
128143
129144 return 1 ;
130145}
131146
147+ int __trace_graph_entry (struct trace_array * tr ,
148+ struct ftrace_graph_ent * trace ,
149+ unsigned int trace_ctx )
150+ {
151+ return __graph_entry (tr , trace , trace_ctx , NULL );
152+ }
153+
132154#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
133155int __trace_graph_retaddr_entry (struct trace_array * tr ,
134156 struct ftrace_graph_ent * trace ,
@@ -174,9 +196,9 @@ struct fgraph_times {
174196 unsigned long long sleeptime ; /* may be optional! */
175197};
176198
177- int trace_graph_entry (struct ftrace_graph_ent * trace ,
178- struct fgraph_ops * gops ,
179- struct ftrace_regs * fregs )
199+ static int graph_entry (struct ftrace_graph_ent * trace ,
200+ struct fgraph_ops * gops ,
201+ struct ftrace_regs * fregs )
180202{
181203 unsigned long * task_var = fgraph_get_task_var (gops );
182204 struct trace_array * tr = gops -> private ;
@@ -246,14 +268,28 @@ int trace_graph_entry(struct ftrace_graph_ent *trace,
246268 unsigned long retaddr = ftrace_graph_top_ret_addr (current );
247269 ret = __trace_graph_retaddr_entry (tr , trace , trace_ctx , retaddr );
248270 } else {
249- ret = __trace_graph_entry (tr , trace , trace_ctx );
271+ ret = __graph_entry (tr , trace , trace_ctx , fregs );
250272 }
251273 }
252274 preempt_enable_notrace ();
253275
254276 return ret ;
255277}
256278
279+ int trace_graph_entry (struct ftrace_graph_ent * trace ,
280+ struct fgraph_ops * gops ,
281+ struct ftrace_regs * fregs )
282+ {
283+ return graph_entry (trace , gops , NULL );
284+ }
285+
286+ static int trace_graph_entry_args (struct ftrace_graph_ent * trace ,
287+ struct fgraph_ops * gops ,
288+ struct ftrace_regs * fregs )
289+ {
290+ return graph_entry (trace , gops , fregs );
291+ }
292+
257293static void
258294__trace_graph_function (struct trace_array * tr ,
259295 unsigned long ip , unsigned int trace_ctx )
@@ -418,7 +454,10 @@ static int graph_trace_init(struct trace_array *tr)
418454{
419455 int ret ;
420456
421- tr -> gops -> entryfunc = trace_graph_entry ;
457+ if (tracer_flags_is_set (TRACE_GRAPH_ARGS ))
458+ tr -> gops -> entryfunc = trace_graph_entry_args ;
459+ else
460+ tr -> gops -> entryfunc = trace_graph_entry ;
422461
423462 if (tracing_thresh )
424463 tr -> gops -> retfunc = trace_graph_thresh_return ;
@@ -775,7 +814,7 @@ static void print_graph_retaddr(struct trace_seq *s, struct fgraph_retaddr_ent_e
775814
776815static void print_graph_retval (struct trace_seq * s , struct ftrace_graph_ent_entry * entry ,
777816 struct ftrace_graph_ret * graph_ret , void * func ,
778- u32 opt_flags , u32 trace_flags )
817+ u32 opt_flags , u32 trace_flags , int args_size )
779818{
780819 unsigned long err_code = 0 ;
781820 unsigned long retval = 0 ;
@@ -809,7 +848,14 @@ static void print_graph_retval(struct trace_seq *s, struct ftrace_graph_ent_entr
809848 if (entry -> ent .type != TRACE_GRAPH_RETADDR_ENT )
810849 print_retaddr = false;
811850
812- trace_seq_printf (s , "%ps();" , func );
851+ trace_seq_printf (s , "%ps" , func );
852+
853+ if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof (long )) {
854+ print_function_args (s , entry -> args , (unsigned long )func );
855+ trace_seq_putc (s , ';' );
856+ } else
857+ trace_seq_puts (s , "();" );
858+
813859 if (print_retval || print_retaddr )
814860 trace_seq_puts (s , " /*" );
815861 else
@@ -836,7 +882,8 @@ static void print_graph_retval(struct trace_seq *s, struct ftrace_graph_ent_entr
836882
837883#else
838884
839- #define print_graph_retval (_seq , _ent , _ret , _func , _opt_flags , _trace_flags ) do {} while (0)
885+ #define print_graph_retval (_seq , _ent , _ret , _func , _opt_flags , _trace_flags , args_size ) \
886+ do {} while (0)
840887
841888#endif
842889
@@ -852,10 +899,14 @@ print_graph_entry_leaf(struct trace_iterator *iter,
852899 struct ftrace_graph_ret * graph_ret ;
853900 struct ftrace_graph_ent * call ;
854901 unsigned long long duration ;
902+ unsigned long ret_func ;
855903 unsigned long func ;
904+ int args_size ;
856905 int cpu = iter -> cpu ;
857906 int i ;
858907
908+ args_size = iter -> ent_size - offsetof(struct ftrace_graph_ent_entry , args );
909+
859910 graph_ret = & ret_entry -> ret ;
860911 call = & entry -> graph_ent ;
861912 duration = ret_entry -> rettime - ret_entry -> calltime ;
@@ -887,16 +938,25 @@ print_graph_entry_leaf(struct trace_iterator *iter,
887938 for (i = 0 ; i < call -> depth * TRACE_GRAPH_INDENT ; i ++ )
888939 trace_seq_putc (s , ' ' );
889940
941+ ret_func = graph_ret -> func + iter -> tr -> text_delta ;
942+
890943 /*
891944 * Write out the function return value or return address
892945 */
893946 if (flags & (__TRACE_GRAPH_PRINT_RETVAL | __TRACE_GRAPH_PRINT_RETADDR )) {
894947 print_graph_retval (s , entry , graph_ret ,
895948 (void * )graph_ret -> func + iter -> tr -> text_delta ,
896- flags , tr -> trace_flags );
949+ flags , tr -> trace_flags , args_size );
897950 } else {
898- trace_seq_printf (s , "%ps();\n" , (void * )func );
951+ trace_seq_printf (s , "%ps" , (void * )ret_func );
952+
953+ if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof (long )) {
954+ print_function_args (s , entry -> args , ret_func );
955+ trace_seq_putc (s , ';' );
956+ } else
957+ trace_seq_puts (s , "();" );
899958 }
959+ trace_seq_printf (s , "\n" );
900960
901961 print_graph_irq (iter , graph_ret -> func , TRACE_GRAPH_RET ,
902962 cpu , iter -> ent -> pid , flags );
@@ -913,6 +973,7 @@ print_graph_entry_nested(struct trace_iterator *iter,
913973 struct fgraph_data * data = iter -> private ;
914974 struct trace_array * tr = iter -> tr ;
915975 unsigned long func ;
976+ int args_size ;
916977 int i ;
917978
918979 if (data ) {
@@ -937,7 +998,17 @@ print_graph_entry_nested(struct trace_iterator *iter,
937998
938999 func = call -> func + iter -> tr -> text_delta ;
9391000
940- trace_seq_printf (s , "%ps() {" , (void * )func );
1001+ trace_seq_printf (s , "%ps" , (void * )func );
1002+
1003+ args_size = iter -> ent_size - offsetof(struct ftrace_graph_ent_entry , args );
1004+
1005+ if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof (long ))
1006+ print_function_args (s , entry -> args , func );
1007+ else
1008+ trace_seq_puts (s , "()" );
1009+
1010+ trace_seq_puts (s , " {" );
1011+
9411012 if (flags & __TRACE_GRAPH_PRINT_RETADDR &&
9421013 entry -> ent .type == TRACE_GRAPH_RETADDR_ENT )
9431014 print_graph_retaddr (s , (struct fgraph_retaddr_ent_entry * )entry ,
@@ -1107,21 +1178,38 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
11071178 struct trace_iterator * iter , u32 flags )
11081179{
11091180 struct fgraph_data * data = iter -> private ;
1110- struct ftrace_graph_ent * call = & field -> graph_ent ;
1181+ struct ftrace_graph_ent * call ;
11111182 struct ftrace_graph_ret_entry * leaf_ret ;
11121183 static enum print_line_t ret ;
11131184 int cpu = iter -> cpu ;
1185+ /*
1186+ * print_graph_entry() may consume the current event,
1187+ * thus @field may become invalid, so we need to save it.
1188+ * sizeof(struct ftrace_graph_ent_entry) is very small,
1189+ * it can be safely saved at the stack.
1190+ */
1191+ struct ftrace_graph_ent_entry * entry ;
1192+ u8 save_buf [sizeof (* entry ) + FTRACE_REGS_MAX_ARGS * sizeof (long )];
1193+
1194+ /* The ent_size is expected to be as big as the entry */
1195+ if (iter -> ent_size > sizeof (save_buf ))
1196+ iter -> ent_size = sizeof (save_buf );
1197+
1198+ entry = (void * )save_buf ;
1199+ memcpy (entry , field , iter -> ent_size );
1200+
1201+ call = & entry -> graph_ent ;
11141202
11151203 if (check_irq_entry (iter , flags , call -> func , call -> depth ))
11161204 return TRACE_TYPE_HANDLED ;
11171205
11181206 print_graph_prologue (iter , s , TRACE_GRAPH_ENT , call -> func , flags );
11191207
1120- leaf_ret = get_return_for_leaf (iter , field );
1208+ leaf_ret = get_return_for_leaf (iter , entry );
11211209 if (leaf_ret )
1122- ret = print_graph_entry_leaf (iter , field , leaf_ret , s , flags );
1210+ ret = print_graph_entry_leaf (iter , entry , leaf_ret , s , flags );
11231211 else
1124- ret = print_graph_entry_nested (iter , field , s , cpu , flags );
1212+ ret = print_graph_entry_nested (iter , entry , s , cpu , flags );
11251213
11261214 if (data ) {
11271215 /*
@@ -1195,7 +1283,8 @@ print_graph_return(struct ftrace_graph_ret_entry *retentry, struct trace_seq *s,
11951283 * funcgraph-retval option is enabled.
11961284 */
11971285 if (flags & __TRACE_GRAPH_PRINT_RETVAL ) {
1198- print_graph_retval (s , NULL , trace , (void * )func , flags , tr -> trace_flags );
1286+ print_graph_retval (s , NULL , trace , (void * )func , flags ,
1287+ tr -> trace_flags , 0 );
11991288 } else {
12001289 /*
12011290 * If the return function does not have a matching entry,
@@ -1323,16 +1412,8 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags)
13231412
13241413 switch (entry -> type ) {
13251414 case TRACE_GRAPH_ENT : {
1326- /*
1327- * print_graph_entry() may consume the current event,
1328- * thus @field may become invalid, so we need to save it.
1329- * sizeof(struct ftrace_graph_ent_entry) is very small,
1330- * it can be safely saved at the stack.
1331- */
1332- struct ftrace_graph_ent_entry saved ;
13331415 trace_assign_type (field , entry );
1334- saved = * field ;
1335- return print_graph_entry (& saved , s , iter , flags );
1416+ return print_graph_entry (field , s , iter , flags );
13361417 }
13371418#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
13381419 case TRACE_GRAPH_RETADDR_ENT : {
0 commit comments