Commit 0d71a2b2 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo
Browse files

perf callchain: Setup callchain properly in pipe mode



Callchains are automatically initialized by checking on event's
sample_type. For pipe mode we need to put this check into attr event
code.

Moving the callchains setup code into callchain_param_setup function and
calling it from attr event process code.

This enables pipe output having callchains, like:

  # perf record -g -e 'raw_syscalls:sys_enter' true | perf script
  # perf record -g -e 'raw_syscalls:sys_enter' true | perf report

Committer notes:

We still need the next patch for the above output to work.

Reported-by: default avatarPaul Khuong <pvk@pvk.ca>
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20200507095024.2789147-5-jolsa@kernel.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 14d3d540
Loading
Loading
Loading
Loading
+22 −11
Original line number Diff line number Diff line
@@ -402,16 +402,7 @@ static int report__setup_sample_type(struct report *rep)
		}
	}

	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
		if ((sample_type & PERF_SAMPLE_REGS_USER) &&
		    (sample_type & PERF_SAMPLE_STACK_USER)) {
			callchain_param.record_mode = CALLCHAIN_DWARF;
			dwarf_callchain_users = true;
		} else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
	callchain_param_setup(sample_type);

	if (rep->stitch_lbr && (callchain_param.record_mode != CALLCHAIN_LBR)) {
		ui__warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"
@@ -1089,6 +1080,26 @@ parse_percent_limit(const struct option *opt, const char *str,
	return 0;
}

static int process_attr(struct perf_tool *tool __maybe_unused,
			union perf_event *event,
			struct evlist **pevlist)
{
	u64 sample_type;
	int err;

	err = perf_event__process_attr(tool, event, pevlist);
	if (err)
		return err;

	/*
	 * Check if we need to enable callchains based
	 * on events sample_type.
	 */
	sample_type = perf_evlist__combined_sample_type(*pevlist);
	callchain_param_setup(sample_type);
	return 0;
}

int cmd_report(int argc, const char **argv)
{
	struct perf_session *session;
@@ -1119,7 +1130,7 @@ int cmd_report(int argc, const char **argv)
			.fork		 = perf_event__process_fork,
			.lost		 = perf_event__process_lost,
			.read		 = process_read_event,
			.attr		 = perf_event__process_attr,
			.attr		 = process_attr,
			.tracing_data	 = perf_event__process_tracing_data,
			.build_id	 = perf_event__process_build_id,
			.id_index	 = perf_event__process_id_index,
+12 −2
Original line number Diff line number Diff line
@@ -2085,6 +2085,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
	struct perf_script *scr = container_of(tool, struct perf_script, tool);
	struct evlist *evlist;
	struct evsel *evsel, *pos;
	u64 sample_type;
	int err;
	static struct evsel_script *es;

@@ -2119,12 +2120,21 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,

	set_print_ip_opts(&evsel->core.attr);

	if (evsel->core.attr.sample_type)
	if (evsel->core.attr.sample_type) {
		err = perf_evsel__check_attr(evsel, scr->session);

		if (err)
			return err;
	}

	/*
	 * Check if we need to enable callchains based
	 * on events sample_type.
	 */
	sample_type = perf_evlist__combined_sample_type(evlist);
	callchain_param_setup(sample_type);
	return 0;
}

static int print_event_with_time(struct perf_tool *tool,
				 union perf_event *event,
				 struct perf_sample *sample,
+14 −0
Original line number Diff line number Diff line
@@ -1599,3 +1599,17 @@ void callchain_cursor_reset(struct callchain_cursor *cursor)
	for (node = cursor->first; node != NULL; node = node->next)
		map__zput(node->ms.map);
}

void callchain_param_setup(u64 sample_type)
{
	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
		if ((sample_type & PERF_SAMPLE_REGS_USER) &&
		    (sample_type & PERF_SAMPLE_STACK_USER)) {
			callchain_param.record_mode = CALLCHAIN_DWARF;
			dwarf_callchain_users = true;
		} else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
			callchain_param.record_mode = CALLCHAIN_LBR;
		else
			callchain_param.record_mode = CALLCHAIN_FP;
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -297,4 +297,5 @@ int callchain_branch_counts(struct callchain_root *root,
			    u64 *branch_count, u64 *predicted_count,
			    u64 *abort_count, u64 *cycles_count);

void callchain_param_setup(u64 sample_type);
#endif	/* __PERF_CALLCHAIN_H */