[PATCH 27/48] perf tools: Use map_groups__find_addr_by_time()

From: Jiri Olsa
Date: Thu Sep 13 2018 - 08:55:59 EST


From: Namhyung Kim <namhyung@xxxxxxxxxx>

Use timestamp to find a corresponding map so that it can find a match
symbol eventually.

Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Link: http://lkml.kernel.org/n/tip-v4i4q9u41ab4hcjispe9qjzk@xxxxxxxxxxxxxx
Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
---
tools/perf/util/event.c | 83 +++++++++++++++++++++++++++++++++++-----
tools/perf/util/thread.c | 8 +++-
2 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 74d20056b860..64ba909aeecb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1516,12 +1516,11 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
return machine__process_event(machine, event, sample);
}

-static
-struct map *map_groups__find_map(struct map_groups *mg, u8 cpumode,
- u64 addr, struct addr_location *al)
+static bool map_groups__set_addr_location(struct map_groups *mg,
+ struct addr_location *al,
+ u8 cpumode, u64 addr)
{
struct machine *machine = mg->machine;
- bool load_map = false;

al->machine = machine;
al->addr = addr;
@@ -1530,21 +1529,17 @@ struct map *map_groups__find_map(struct map_groups *mg, u8 cpumode,

if (machine == NULL) {
al->map = NULL;
- return NULL;
+ return true;
}

BUG_ON(mg == NULL);

if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
al->level = 'k';
- mg = &machine->kmaps;
- load_map = true;
} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
al->level = '.';
} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
al->level = 'g';
- mg = &machine->kmaps;
- load_map = true;
} else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
al->level = 'u';
} else {
@@ -1560,8 +1555,27 @@ struct map *map_groups__find_map(struct map_groups *mg, u8 cpumode,
!perf_host)
al->filtered |= (1 << HIST_FILTER__HOST);

+ return true;
+ }
+ return false;
+}
+
+static
+struct map *map_groups__find_map(struct map_groups *mg, u8 cpumode,
+ u64 addr, struct addr_location *al)
+{
+ struct machine *machine = mg->machine;
+ bool load_map = false;
+
+ if (map_groups__set_addr_location(mg, al, cpumode, addr))
return NULL;
+
+ if ((cpumode == PERF_RECORD_MISC_KERNEL && perf_host) ||
+ (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)) {
+ mg = &machine->kmaps;
+ load_map = true;
}
+
try_again:
al->map = map_groups__find(mg, al->addr);
if (al->map == NULL) {
@@ -1594,6 +1608,55 @@ struct map *map_groups__find_map(struct map_groups *mg, u8 cpumode,
return al->map;
}

+static
+struct map *map_groups__find_map_by_time(struct map_groups *mg, u8 cpumode,
+ u64 addr, struct addr_location *al,
+ u64 timestamp)
+{
+ struct machine *machine = mg->machine;
+ bool load_map = false;
+
+ if (map_groups__set_addr_location(mg, al, cpumode, addr))
+ return NULL;
+
+ if ((cpumode == PERF_RECORD_MISC_KERNEL && perf_host) ||
+ (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)) {
+ mg = &machine->kmaps;
+ load_map = true;
+ }
+
+try_again:
+ al->map = map_groups__find_by_time(mg, al->addr, timestamp);
+ if (al->map == NULL) {
+ /*
+ * If this is outside of all known maps, and is a negative
+ * address, try to look it up in the kernel dso, as it might be
+ * a vsyscall or vdso (which executes in user-mode).
+ *
+ * XXX This is nasty, we should have a symbol list in the
+ * "[vdso]" dso, but for now lets use the old trick of looking
+ * in the whole kernel symbol list.
+ */
+ if (cpumode == PERF_RECORD_MISC_USER && machine &&
+ mg != &machine->kmaps &&
+ machine__kernel_ip(machine, al->addr)) {
+ mg = &machine->kmaps;
+ load_map = true;
+ goto try_again;
+ }
+ } else {
+ /*
+ * Kernel maps might be changed when loading symbols so loading
+ * must be done prior to using kernel maps.
+ */
+ if (load_map)
+ map__load(al->map);
+ al->addr = al->map->map_ip(al->map, al->addr);
+ }
+
+ return al->map;
+}
+
struct map *thread__find_map(struct thread *thread, u8 cpumode,
u64 addr, struct addr_location *al)
{
@@ -1613,7 +1676,7 @@ struct map *thread__find_map_by_time(struct thread *thread, u8 cpumode,
mg = thread->mg;

al->thread = thread;
- return map_groups__find_map(mg, cpumode, addr, al);
+ return map_groups__find_map_by_time(mg, cpumode, addr, al, timestamp);
}

struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 8a0b27202ab7..491761752ac6 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -449,8 +449,12 @@ int thread__insert_map(struct thread *thread, struct map *map)
if (ret)
return ret;

- map_groups__fixup_overlappings(thread->mg, map, stderr);
- map_groups__insert(thread->mg, map);
+ if (perf_has_index) {
+ map_groups__insert_by_time(thread->mg, map);
+ } else {
+ map_groups__fixup_overlappings(thread->mg, map, stderr);
+ map_groups__insert(thread->mg, map);
+ }

return 0;
}
--
2.17.1