Commit fa7095c5 authored by James Clark's avatar James Clark Committed by Arnaldo Carvalho de Melo
Browse files

perf unwind: Don't show unwind error messages when augmenting frame pointer stack



Commit Fixes: b9f6fbb3 ("perf arm64: Inject missing frames when
using 'perf record --call-graph=fp'") intended to add a 'best effort'
DWARF unwind that improved the frame pointer stack in most scenarios.

It's expected that the unwind will fail sometimes, but this shouldn't be
reported as an error. It only works when the return address can be
determined from the contents of the link register alone.

Fix the error shown when the unwinder requires extra registers by adding
a new flag that suppresses error messages. This flag is not set in the
normal --call-graph=dwarf unwind mode so that behavior is not changed.

Fixes: b9f6fbb3 ("perf arm64: Inject missing frames when using 'perf record --call-graph=fp'")
Reported-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarJames Clark <james.clark@arm.com>
Tested-by: default avatarJohn Garry <john.garry@huawei.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Truong <alexandre.truong@arm.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20220406145651.1392529-1-james.clark@arm.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 278aaba2
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -122,7 +122,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thr
	}
	}


	err = unwind__get_entries(unwind_entry, &cnt, thread,
	err = unwind__get_entries(unwind_entry, &cnt, thread,
				  &sample, MAX_STACK);
				  &sample, MAX_STACK, false);
	if (err)
	if (err)
		pr_debug("unwind failed\n");
		pr_debug("unwind failed\n");
	else if (cnt != MAX_STACK) {
	else if (cnt != MAX_STACK) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -53,7 +53,7 @@ u64 get_leaf_frame_caller_aarch64(struct perf_sample *sample, struct thread *thr
		sample->user_regs.cache_regs[PERF_REG_ARM64_SP] = 0;
		sample->user_regs.cache_regs[PERF_REG_ARM64_SP] = 0;
	}
	}


	ret = unwind__get_entries(add_entry, &entries, thread, sample, 2);
	ret = unwind__get_entries(add_entry, &entries, thread, sample, 2, true);
	sample->user_regs = old_regs;
	sample->user_regs = old_regs;


	if (ret || entries.length != 2)
	if (ret || entries.length != 2)
+1 −1
Original line number Original line Diff line number Diff line
@@ -2987,7 +2987,7 @@ static int thread__resolve_callchain_unwind(struct thread *thread,
		return 0;
		return 0;


	return unwind__get_entries(unwind_entry, cursor,
	return unwind__get_entries(unwind_entry, cursor,
				   thread, sample, max_stack);
				   thread, sample, max_stack, false);
}
}


int thread__resolve_callchain(struct thread *thread,
int thread__resolve_callchain(struct thread *thread,
+7 −3
Original line number Original line Diff line number Diff line
@@ -200,6 +200,7 @@ frame_callback(Dwfl_Frame *state, void *arg)
	bool isactivation;
	bool isactivation;


	if (!dwfl_frame_pc(state, &pc, NULL)) {
	if (!dwfl_frame_pc(state, &pc, NULL)) {
		if (!ui->best_effort)
			pr_err("%s", dwfl_errmsg(-1));
			pr_err("%s", dwfl_errmsg(-1));
		return DWARF_CB_ABORT;
		return DWARF_CB_ABORT;
	}
	}
@@ -208,6 +209,7 @@ frame_callback(Dwfl_Frame *state, void *arg)
	report_module(pc, ui);
	report_module(pc, ui);


	if (!dwfl_frame_pc(state, &pc, &isactivation)) {
	if (!dwfl_frame_pc(state, &pc, &isactivation)) {
		if (!ui->best_effort)
			pr_err("%s", dwfl_errmsg(-1));
			pr_err("%s", dwfl_errmsg(-1));
		return DWARF_CB_ABORT;
		return DWARF_CB_ABORT;
	}
	}
@@ -222,7 +224,8 @@ frame_callback(Dwfl_Frame *state, void *arg)
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
			struct thread *thread,
			struct thread *thread,
			struct perf_sample *data,
			struct perf_sample *data,
			int max_stack)
			int max_stack,
			bool best_effort)
{
{
	struct unwind_info *ui, ui_buf = {
	struct unwind_info *ui, ui_buf = {
		.sample		= data,
		.sample		= data,
@@ -231,6 +234,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
		.cb		= cb,
		.cb		= cb,
		.arg		= arg,
		.arg		= arg,
		.max_stack	= max_stack,
		.max_stack	= max_stack,
		.best_effort    = best_effort
	};
	};
	Dwarf_Word ip;
	Dwarf_Word ip;
	int err = -EINVAL, i;
	int err = -EINVAL, i;
+1 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ struct unwind_info {
	void			*arg;
	void			*arg;
	int			max_stack;
	int			max_stack;
	int			idx;
	int			idx;
	bool			best_effort;
	struct unwind_entry	entries[];
	struct unwind_entry	entries[];
};
};


Loading