diff options
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r-- | tools/perf/builtin-trace.c | 83 |
1 files changed, 80 insertions, 3 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 297aeaa9f69d..8303d83cb93c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -175,6 +175,7 @@ struct trace { bool print_sample; bool show_tool_stats; bool trace_syscalls; + bool libtraceevent_print; bool kernel_syscallchains; s16 args_alignment; bool show_tstamp; @@ -2397,6 +2398,71 @@ static void bpf_output__fprintf(struct trace *trace, ++trace->nr_events_printed; } +static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel, struct perf_sample *sample, + struct thread *thread, void *augmented_args, int augmented_args_size) +{ + char bf[2048]; + size_t size = sizeof(bf); + struct tep_format_field *field = evsel->tp_format->format.fields; + struct syscall_arg_fmt *arg = evsel->priv; + size_t printed = 0; + unsigned long val; + u8 bit = 1; + struct syscall_arg syscall_arg = { + .augmented = { + .size = augmented_args_size, + .args = augmented_args, + }, + .idx = 0, + .mask = 0, + .trace = trace, + .thread = thread, + .show_string_prefix = trace->show_string_prefix, + }; + + for (; field && arg; field = field->next, ++syscall_arg.idx, bit <<= 1, ++arg) { + if (syscall_arg.mask & bit) + continue; + + syscall_arg.fmt = arg; + if (field->flags & TEP_FIELD_IS_ARRAY) + val = (uintptr_t)(sample->raw_data + field->offset); + else + val = format_field__intval(field, sample, evsel->needs_swap); + /* + * Some syscall args need some mask, most don't and + * return val untouched. + */ + val = syscall_arg_fmt__mask_val(arg, &syscall_arg, val); + + /* + * Suppress this argument if its value is zero and + * and we don't have a string associated in an + * strarray for it. + */ + if (val == 0 && + !trace->show_zeros && + !((arg->show_zero || + arg->scnprintf == SCA_STRARRAY || + arg->scnprintf == SCA_STRARRAYS) && + arg->parm)) + continue; + + printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : ""); + + /* + * XXX Perhaps we should have a show_tp_arg_names, + * leaving show_arg_names just for syscalls? + */ + if (1 || trace->show_arg_names) + printed += scnprintf(bf + printed, size - printed, "%s: ", field->name); + + printed += syscall_arg_fmt__scnprintf_val(arg, bf + printed, size - printed, &syscall_arg, val); + } + + return printed + fprintf(trace->output, "%s", bf); +} + static int trace__event_handler(struct trace *trace, struct evsel *evsel, union perf_event *event __maybe_unused, struct perf_sample *sample) @@ -2457,9 +2523,13 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel, } else if (evsel->tp_format) { if (strncmp(evsel->tp_format->name, "sys_enter_", 10) || trace__fprintf_sys_enter(trace, evsel, sample)) { - event_format__fprintf(evsel->tp_format, sample->cpu, - sample->raw_data, sample->raw_size, - trace->output); + if (trace->libtraceevent_print) { + event_format__fprintf(evsel->tp_format, sample->cpu, + sample->raw_data, sample->raw_size, + trace->output); + } else { + trace__fprintf_tp_fields(trace, evsel, sample, thread, NULL, 0); + } ++trace->nr_events_printed; if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) { @@ -4150,6 +4220,11 @@ static int trace__config(const char *var, const char *value, void *arg) int args_alignment = 0; if (perf_config_int(&args_alignment, var, value) == 0) trace->args_alignment = args_alignment; + } else if (!strcmp(var, "trace.tracepoint_beautifiers")) { + if (strcasecmp(value, "libtraceevent") == 0) + trace->libtraceevent_print = true; + else if (strcasecmp(value, "libbeauty") == 0) + trace->libtraceevent_print = false; } out: return err; @@ -4239,6 +4314,8 @@ int cmd_trace(int argc, const char **argv) OPT_CALLBACK(0, "call-graph", &trace.opts, "record_mode[,record_size]", record_callchain_help, &record_parse_callchain_opt), + OPT_BOOLEAN(0, "libtraceevent_print", &trace.libtraceevent_print, + "Use libtraceevent to print the tracepoint arguments."), OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, "Show the kernel callchains on the syscall exit path"), OPT_ULONG(0, "max-events", &trace.max_events, |