| From 7aa412a86eeef85d10f28cde9e6a481be0086857 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 30 Oct 2019 16:09:49 +0900 |
| Subject: perf probe: Skip overlapped location on searching variables |
| |
| From: Masami Hiramatsu <mhiramat@kernel.org> |
| |
| [ Upstream commit dee36a2abb67c175265d49b9a8c7dfa564463d9a ] |
| |
| Since debuginfo__find_probes() callback function can be called with the |
| location which already passed, the callback function must filter out |
| such overlapped locations. |
| |
| add_probe_trace_event() has already done it by commit 1a375ae7659a |
| ("perf probe: Skip same probe address for a given line"), but |
| add_available_vars() doesn't. Thus perf probe -v shows same address |
| repeatedly as below: |
| |
| # perf probe -V vfs_read:18 |
| Available variables at vfs_read:18 |
| @<vfs_read+217> |
| char* buf |
| loff_t* pos |
| ssize_t ret |
| struct file* file |
| @<vfs_read+217> |
| char* buf |
| loff_t* pos |
| ssize_t ret |
| struct file* file |
| @<vfs_read+226> |
| char* buf |
| loff_t* pos |
| ssize_t ret |
| struct file* file |
| |
| With this fix, perf probe -V shows it correctly: |
| |
| # perf probe -V vfs_read:18 |
| Available variables at vfs_read:18 |
| @<vfs_read+217> |
| char* buf |
| loff_t* pos |
| ssize_t ret |
| struct file* file |
| @<vfs_read+226> |
| char* buf |
| loff_t* pos |
| ssize_t ret |
| struct file* file |
| |
| Fixes: cf6eb489e5c0 ("perf probe: Show accessible local variables") |
| Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> |
| Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Cc: Jiri Olsa <jolsa@redhat.com> |
| Cc: Namhyung Kim <namhyung@kernel.org> |
| Link: http://lore.kernel.org/lkml/157241938927.32002.4026859017790562751.stgit@devnote2 |
| Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| tools/perf/util/probe-finder.c | 20 ++++++++++++++++++++ |
| 1 file changed, 20 insertions(+) |
| |
| diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c |
| index aa6b35726976..e1d0bbf7735b 100644 |
| --- a/tools/perf/util/probe-finder.c |
| +++ b/tools/perf/util/probe-finder.c |
| @@ -1417,6 +1417,18 @@ error: |
| return DIE_FIND_CB_END; |
| } |
| |
| +static bool available_var_finder_overlap(struct available_var_finder *af) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < af->nvls; i++) { |
| + if (af->pf.addr == af->vls[i].point.address) |
| + return true; |
| + } |
| + return false; |
| + |
| +} |
| + |
| /* Add a found vars into available variables list */ |
| static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) |
| { |
| @@ -1427,6 +1439,14 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) |
| Dwarf_Die die_mem; |
| int ret; |
| |
| + /* |
| + * For some reason (e.g. different column assigned to same address), |
| + * this callback can be called with the address which already passed. |
| + * Ignore it first. |
| + */ |
| + if (available_var_finder_overlap(af)) |
| + return 0; |
| + |
| /* Check number of tevs */ |
| if (af->nvls == af->max_vls) { |
| pr_warning("Too many( > %d) probe point found.\n", af->max_vls); |
| -- |
| 2.20.1 |
| |