Skip to content

Commit 76fe033

Browse files
svens-s390rostedt
authored andcommitted
ftrace: Add arguments to function tracer
Wire up the code to print function arguments in the function tracer. This functionality can be enabled/disabled during runtime with options/func-args. ping-689 [004] b.... 77.170220: dummy_xmit(skb = 0x82904800, dev = 0x882d0000) <-dev_hard_start_xmit Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Albert Ou <[email protected]> Cc: Guo Ren <[email protected]> Cc: Donglin Peng <[email protected]> Cc: Zheng Yejian <[email protected]> Link: https://lore.kernel.org/[email protected] Reviewed-by: Masami Hiramatsu (Google) <[email protected]> Co-developed-by: Steven Rostedt (Google) <[email protected]> Signed-off-by: Sven Schnelle <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent c7a60a7 commit 76fe033

File tree

7 files changed

+85
-18
lines changed

7 files changed

+85
-18
lines changed

kernel/trace/trace.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,20 +2878,30 @@ trace_buffer_unlock_commit_nostack(struct trace_buffer *buffer,
28782878

28792879
void
28802880
trace_function(struct trace_array *tr, unsigned long ip, unsigned long
2881-
parent_ip, unsigned int trace_ctx)
2881+
parent_ip, unsigned int trace_ctx, struct ftrace_regs *fregs)
28822882
{
28832883
struct trace_buffer *buffer = tr->array_buffer.buffer;
28842884
struct ring_buffer_event *event;
28852885
struct ftrace_entry *entry;
2886+
int size = sizeof(*entry);
28862887

2887-
event = __trace_buffer_lock_reserve(buffer, TRACE_FN, sizeof(*entry),
2888+
size += FTRACE_REGS_MAX_ARGS * !!fregs * sizeof(long);
2889+
2890+
event = __trace_buffer_lock_reserve(buffer, TRACE_FN, size,
28882891
trace_ctx);
28892892
if (!event)
28902893
return;
28912894
entry = ring_buffer_event_data(event);
28922895
entry->ip = ip;
28932896
entry->parent_ip = parent_ip;
28942897

2898+
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
2899+
if (fregs) {
2900+
for (int i = 0; i < FTRACE_REGS_MAX_ARGS; i++)
2901+
entry->args[i] = ftrace_regs_get_argument(fregs, i);
2902+
}
2903+
#endif
2904+
28952905
if (static_branch_unlikely(&trace_function_exports_enabled))
28962906
ftrace_exports(event, TRACE_EXPORT_FUNCTION);
28972907
__buffer_unlock_commit(buffer, event);

kernel/trace/trace.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/workqueue.h>
2222
#include <linux/ctype.h>
2323
#include <linux/once_lite.h>
24+
#include <linux/ftrace_regs.h>
2425

2526
#include "pid_list.h"
2627

@@ -697,7 +698,8 @@ unsigned long trace_total_entries(struct trace_array *tr);
697698
void trace_function(struct trace_array *tr,
698699
unsigned long ip,
699700
unsigned long parent_ip,
700-
unsigned int trace_ctx);
701+
unsigned int trace_ctx,
702+
struct ftrace_regs *regs);
701703
void trace_graph_function(struct trace_array *tr,
702704
unsigned long ip,
703705
unsigned long parent_ip,

kernel/trace/trace_entries.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ FTRACE_ENTRY_REG(function, ftrace_entry,
6161
TRACE_FN,
6262

6363
F_STRUCT(
64-
__field_fn( unsigned long, ip )
65-
__field_fn( unsigned long, parent_ip )
64+
__field_fn( unsigned long, ip )
65+
__field_fn( unsigned long, parent_ip )
66+
__dynamic_array( unsigned long, args )
6667
),
6768

6869
F_printk(" %ps <-- %ps",

kernel/trace/trace_functions.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ static void
2525
function_trace_call(unsigned long ip, unsigned long parent_ip,
2626
struct ftrace_ops *op, struct ftrace_regs *fregs);
2727
static void
28+
function_args_trace_call(unsigned long ip, unsigned long parent_ip,
29+
struct ftrace_ops *op, struct ftrace_regs *fregs);
30+
static void
2831
function_stack_trace_call(unsigned long ip, unsigned long parent_ip,
2932
struct ftrace_ops *op, struct ftrace_regs *fregs);
3033
static void
@@ -42,9 +45,10 @@ enum {
4245
TRACE_FUNC_NO_OPTS = 0x0, /* No flags set. */
4346
TRACE_FUNC_OPT_STACK = 0x1,
4447
TRACE_FUNC_OPT_NO_REPEATS = 0x2,
48+
TRACE_FUNC_OPT_ARGS = 0x4,
4549

4650
/* Update this to next highest bit. */
47-
TRACE_FUNC_OPT_HIGHEST_BIT = 0x4
51+
TRACE_FUNC_OPT_HIGHEST_BIT = 0x8
4852
};
4953

5054
#define TRACE_FUNC_OPT_MASK (TRACE_FUNC_OPT_HIGHEST_BIT - 1)
@@ -114,6 +118,8 @@ static ftrace_func_t select_trace_function(u32 flags_val)
114118
switch (flags_val & TRACE_FUNC_OPT_MASK) {
115119
case TRACE_FUNC_NO_OPTS:
116120
return function_trace_call;
121+
case TRACE_FUNC_OPT_ARGS:
122+
return function_args_trace_call;
117123
case TRACE_FUNC_OPT_STACK:
118124
return function_stack_trace_call;
119125
case TRACE_FUNC_OPT_NO_REPEATS:
@@ -220,7 +226,34 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
220226

221227
data = this_cpu_ptr(tr->array_buffer.data);
222228
if (!atomic_read(&data->disabled))
223-
trace_function(tr, ip, parent_ip, trace_ctx);
229+
trace_function(tr, ip, parent_ip, trace_ctx, NULL);
230+
231+
ftrace_test_recursion_unlock(bit);
232+
}
233+
234+
static void
235+
function_args_trace_call(unsigned long ip, unsigned long parent_ip,
236+
struct ftrace_ops *op, struct ftrace_regs *fregs)
237+
{
238+
struct trace_array *tr = op->private;
239+
struct trace_array_cpu *data;
240+
unsigned int trace_ctx;
241+
int bit;
242+
int cpu;
243+
244+
if (unlikely(!tr->function_enabled))
245+
return;
246+
247+
bit = ftrace_test_recursion_trylock(ip, parent_ip);
248+
if (bit < 0)
249+
return;
250+
251+
trace_ctx = tracing_gen_ctx();
252+
253+
cpu = smp_processor_id();
254+
data = per_cpu_ptr(tr->array_buffer.data, cpu);
255+
if (!atomic_read(&data->disabled))
256+
trace_function(tr, ip, parent_ip, trace_ctx, fregs);
224257

225258
ftrace_test_recursion_unlock(bit);
226259
}
@@ -270,7 +303,7 @@ function_stack_trace_call(unsigned long ip, unsigned long parent_ip,
270303

271304
if (likely(disabled == 1)) {
272305
trace_ctx = tracing_gen_ctx_flags(flags);
273-
trace_function(tr, ip, parent_ip, trace_ctx);
306+
trace_function(tr, ip, parent_ip, trace_ctx, NULL);
274307
#ifdef CONFIG_UNWINDER_FRAME_POINTER
275308
if (ftrace_pids_enabled(op))
276309
skip++;
@@ -349,7 +382,7 @@ function_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
349382
trace_ctx = tracing_gen_ctx_dec();
350383
process_repeats(tr, ip, parent_ip, last_info, trace_ctx);
351384

352-
trace_function(tr, ip, parent_ip, trace_ctx);
385+
trace_function(tr, ip, parent_ip, trace_ctx, NULL);
353386

354387
out:
355388
ftrace_test_recursion_unlock(bit);
@@ -389,7 +422,7 @@ function_stack_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
389422
trace_ctx = tracing_gen_ctx_flags(flags);
390423
process_repeats(tr, ip, parent_ip, last_info, trace_ctx);
391424

392-
trace_function(tr, ip, parent_ip, trace_ctx);
425+
trace_function(tr, ip, parent_ip, trace_ctx, NULL);
393426
__trace_stack(tr, trace_ctx, STACK_SKIP);
394427
}
395428

@@ -403,6 +436,9 @@ static struct tracer_opt func_opts[] = {
403436
{ TRACER_OPT(func_stack_trace, TRACE_FUNC_OPT_STACK) },
404437
#endif
405438
{ TRACER_OPT(func-no-repeats, TRACE_FUNC_OPT_NO_REPEATS) },
439+
#ifdef CONFIG_FUNCTION_TRACE_ARGS
440+
{ TRACER_OPT(func-args, TRACE_FUNC_OPT_ARGS) },
441+
#endif
406442
{ } /* Always set a last empty entry */
407443
};
408444

kernel/trace/trace_irqsoff.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip,
150150

151151
trace_ctx = tracing_gen_ctx_flags(flags);
152152

153-
trace_function(tr, ip, parent_ip, trace_ctx);
153+
trace_function(tr, ip, parent_ip, trace_ctx, fregs);
154154

155155
atomic_dec(&data->disabled);
156156
}
@@ -295,11 +295,17 @@ __trace_function(struct trace_array *tr,
295295
if (is_graph(tr))
296296
trace_graph_function(tr, ip, parent_ip, trace_ctx);
297297
else
298-
trace_function(tr, ip, parent_ip, trace_ctx);
298+
trace_function(tr, ip, parent_ip, trace_ctx, NULL);
299299
}
300300

301301
#else
302-
#define __trace_function trace_function
302+
static inline void
303+
__trace_function(struct trace_array *tr,
304+
unsigned long ip, unsigned long parent_ip,
305+
unsigned int trace_ctx)
306+
{
307+
return trace_function(tr, ip, parent_ip, trace_ctx, NULL);
308+
}
303309

304310
static enum print_line_t irqsoff_print_line(struct trace_iterator *iter)
305311
{

kernel/trace/trace_output.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,12 +1090,15 @@ enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags,
10901090
}
10911091

10921092
static void print_fn_trace(struct trace_seq *s, unsigned long ip,
1093-
unsigned long parent_ip, long delta, int flags)
1093+
unsigned long parent_ip, long delta,
1094+
unsigned long *args, int flags)
10941095
{
10951096
ip += delta;
10961097
parent_ip += delta;
10971098

10981099
seq_print_ip_sym(s, ip, flags);
1100+
if (args)
1101+
print_function_args(s, args, ip);
10991102

11001103
if ((flags & TRACE_ITER_PRINT_PARENT) && parent_ip) {
11011104
trace_seq_puts(s, " <-");
@@ -1109,10 +1112,19 @@ static enum print_line_t trace_fn_trace(struct trace_iterator *iter, int flags,
11091112
{
11101113
struct ftrace_entry *field;
11111114
struct trace_seq *s = &iter->seq;
1115+
unsigned long *args;
1116+
int args_size;
11121117

11131118
trace_assign_type(field, iter->ent);
11141119

1115-
print_fn_trace(s, field->ip, field->parent_ip, iter->tr->text_delta, flags);
1120+
args_size = iter->ent_size - offsetof(struct ftrace_entry, args);
1121+
if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof(long))
1122+
args = field->args;
1123+
else
1124+
args = NULL;
1125+
1126+
print_fn_trace(s, field->ip, field->parent_ip, iter->tr->text_delta,
1127+
args, flags);
11161128
trace_seq_putc(s, '\n');
11171129

11181130
return trace_handle_return(s);
@@ -1785,7 +1797,7 @@ trace_func_repeats_print(struct trace_iterator *iter, int flags,
17851797

17861798
trace_assign_type(field, iter->ent);
17871799

1788-
print_fn_trace(s, field->ip, field->parent_ip, iter->tr->text_delta, flags);
1800+
print_fn_trace(s, field->ip, field->parent_ip, iter->tr->text_delta, NULL, flags);
17891801
trace_seq_printf(s, " (repeats: %u, last_ts:", field->count);
17901802
trace_print_time(s, iter,
17911803
iter->ts - FUNC_REPEATS_GET_DELTA_TS(field));

kernel/trace/trace_sched_wakeup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip,
242242
return;
243243

244244
local_irq_save(flags);
245-
trace_function(tr, ip, parent_ip, trace_ctx);
245+
trace_function(tr, ip, parent_ip, trace_ctx, fregs);
246246
local_irq_restore(flags);
247247

248248
atomic_dec(&data->disabled);
@@ -327,7 +327,7 @@ __trace_function(struct trace_array *tr,
327327
if (is_graph(tr))
328328
trace_graph_function(tr, ip, parent_ip, trace_ctx);
329329
else
330-
trace_function(tr, ip, parent_ip, trace_ctx);
330+
trace_function(tr, ip, parent_ip, trace_ctx, NULL);
331331
}
332332

333333
static int wakeup_flag_changed(struct trace_array *tr, u32 mask, int set)

0 commit comments

Comments
 (0)