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

Cc: Stephane Eranian <eran...@google.com>
Signed-off-by: Namhyung Kim <namhy...@kernel.org>
---
 tools/perf/util/event.c  | 81 ++++++++++++++++++++++++++++++++++++++++++------
 tools/perf/util/thread.c |  8 +++--
 2 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index c960cbcd30d4..d7997105ee7a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -895,12 +895,11 @@ int perf_event__process(struct perf_tool *tool 
__maybe_unused,
        return machine__process_event(machine, event, sample);
 }
 
-static void map_groups__find_addr_map(struct map_groups *mg, u8 cpumode,
-                                     enum map_type type, 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;
@@ -909,21 +908,17 @@ static void map_groups__find_addr_map(struct map_groups 
*mg, u8 cpumode,
 
        if (machine == NULL) {
                al->map = NULL;
-               return;
+               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 {
@@ -939,8 +934,27 @@ static void map_groups__find_addr_map(struct map_groups 
*mg, u8 cpumode,
                        !perf_host)
                        al->filtered |= (1 << HIST_FILTER__HOST);
 
+               return true;
+       }
+       return false;
+}
+
+static void map_groups__find_addr_map(struct map_groups *mg, u8 cpumode,
+                                     enum map_type type, 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;
+
+       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, type, al->addr);
        if (al->map == NULL) {
@@ -971,6 +985,53 @@ try_again:
        }
 }
 
+static void map_groups__find_addr_map_by_time(struct map_groups *mg, u8 
cpumode,
+                                             enum map_type type, 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;
+
+       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, type, 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, machine->symbol_filter);
+               al->addr = al->map->map_ip(al->map, al->addr);
+       }
+}
+
 void thread__find_addr_map(struct thread *thread, u8 cpumode,
                           enum map_type type, u64 addr,
                           struct addr_location *al)
@@ -991,7 +1052,7 @@ void thread__find_addr_map_by_time(struct thread *thread, 
u8 cpumode,
                mg = thread->mg;
 
        al->thread = thread;
-       map_groups__find_addr_map(mg, cpumode, type, addr, al);
+       map_groups__find_addr_map_by_time(mg, cpumode, type, addr, al, 
timestamp);
 }
 
 void thread__find_addr_location(struct thread *thread,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index efd510d5d966..21de681415f4 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -337,8 +337,12 @@ size_t thread__fprintf(struct thread *thread, FILE *fp)
 
 void thread__insert_map(struct thread *thread, struct map *map)
 {
-       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);
+       }
 }
 
 static int thread__clone_map_groups(struct thread *thread,
-- 
2.6.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to