perf session: Adopt resolve_callchain
[deliverable/linux.git] / tools / perf / util / session.c
index fe87a2f2e5a52cf72b00d6926ecc11144a121db3..ecd54bedfb1c5f7678c82d657cea8bb0006f1ee7 100644 (file)
@@ -4,6 +4,7 @@
 #include <sys/types.h>
 
 #include "session.h"
+#include "sort.h"
 #include "util.h"
 
 static int perf_session__open(struct perf_session *self, bool force)
@@ -90,3 +91,61 @@ void perf_session__delete(struct perf_session *self)
        free(self->cwd);
        free(self);
 }
+
+static bool symbol__match_parent_regex(struct symbol *sym)
+{
+       if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
+               return 1;
+
+       return 0;
+}
+
+struct symbol **perf_session__resolve_callchain(struct perf_session *self,
+                                               struct thread *thread,
+                                               struct ip_callchain *chain,
+                                               struct symbol **parent)
+{
+       u8 cpumode = PERF_RECORD_MISC_USER;
+       struct symbol **syms = NULL;
+       unsigned int i;
+
+       if (self->use_callchain) {
+               syms = calloc(chain->nr, sizeof(*syms));
+               if (!syms) {
+                       fprintf(stderr, "Can't allocate memory for symbols\n");
+                       exit(-1);
+               }
+       }
+
+       for (i = 0; i < chain->nr; i++) {
+               u64 ip = chain->ips[i];
+               struct addr_location al;
+
+               if (ip >= PERF_CONTEXT_MAX) {
+                       switch (ip) {
+                       case PERF_CONTEXT_HV:
+                               cpumode = PERF_RECORD_MISC_HYPERVISOR;  break;
+                       case PERF_CONTEXT_KERNEL:
+                               cpumode = PERF_RECORD_MISC_KERNEL;      break;
+                       case PERF_CONTEXT_USER:
+                               cpumode = PERF_RECORD_MISC_USER;        break;
+                       default:
+                               break;
+                       }
+                       continue;
+               }
+
+               thread__find_addr_location(thread, self, cpumode,
+                                          MAP__FUNCTION, ip, &al, NULL);
+               if (al.sym != NULL) {
+                       if (sort__has_parent && !*parent &&
+                           symbol__match_parent_regex(al.sym))
+                               *parent = al.sym;
+                       if (!self->use_callchain)
+                               break;
+                       syms[i] = al.sym;
+               }
+       }
+
+       return syms;
+}
This page took 0.025764 seconds and 5 git commands to generate.