- Update to 3.4-rc3.
[linux-flexiantxendom0-3.2.10.git] / tools / perf / util / session.c
index 675e080..00923cd 100644 (file)
@@ -10,6 +10,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "session.h"
+#include "tool.h"
 #include "sort.h"
 #include "util.h"
 #include "cpumap.h"
@@ -23,7 +24,7 @@ static int perf_session__open(struct perf_session *self, bool force)
                self->fd = STDIN_FILENO;
 
                if (perf_session__read_header(self, self->fd) < 0)
-                       pr_err("incompatible file format");
+                       pr_err("incompatible file format (rerun with -v to learn more)");
 
                return 0;
        }
@@ -55,7 +56,7 @@ static int perf_session__open(struct perf_session *self, bool force)
        }
 
        if (perf_session__read_header(self, self->fd) < 0) {
-               pr_err("incompatible file format");
+               pr_err("incompatible file format (rerun with -v to learn more)");
                goto out_close;
        }
 
@@ -84,6 +85,7 @@ void perf_session__update_sample_type(struct perf_session *self)
        self->sample_size = __perf_evsel__sample_size(self->sample_type);
        self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
        self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
+       self->host_machine.id_hdr_size = self->id_hdr_size;
 }
 
 int perf_session__create_kernel_maps(struct perf_session *self)
@@ -103,10 +105,21 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
 
 struct perf_session *perf_session__new(const char *filename, int mode,
                                       bool force, bool repipe,
-                                      struct perf_event_ops *ops)
+                                      struct perf_tool *tool)
 {
-       size_t len = filename ? strlen(filename) + 1 : 0;
-       struct perf_session *self = zalloc(sizeof(*self) + len);
+       struct perf_session *self;
+       struct stat st;
+       size_t len;
+
+       if (!filename || !strlen(filename)) {
+               if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
+                       filename = "-";
+               else
+                       filename = "perf.data";
+       }
+
+       len = strlen(filename);
+       self = zalloc(sizeof(*self) + len);
 
        if (self == NULL)
                goto out;
@@ -127,6 +140,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
        INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
        INIT_LIST_HEAD(&self->ordered_samples.to_free);
        machine__init(&self->host_machine, "", HOST_KERNEL_ID);
+       hists__init(&self->hists);
 
        if (mode == O_RDONLY) {
                if (perf_session__open(self, force) < 0)
@@ -141,10 +155,10 @@ struct perf_session *perf_session__new(const char *filename, int mode,
                        goto out_delete;
        }
 
-       if (ops && ops->ordering_requires_timestamps &&
-           ops->ordered_samples && !self->sample_id_all) {
+       if (tool && tool->ordering_requires_timestamps &&
+           tool->ordered_samples && !self->sample_id_all) {
                dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
-               ops->ordered_samples = false;
+               tool->ordered_samples = false;
        }
 
 out:
@@ -216,16 +230,74 @@ static bool symbol__match_parent_regex(struct symbol *sym)
        return 0;
 }
 
-int perf_session__resolve_callchain(struct perf_session *self,
-                                   struct thread *thread,
-                                   struct ip_callchain *chain,
-                                   struct symbol **parent)
+static const u8 cpumodes[] = {
+       PERF_RECORD_MISC_USER,
+       PERF_RECORD_MISC_KERNEL,
+       PERF_RECORD_MISC_GUEST_USER,
+       PERF_RECORD_MISC_GUEST_KERNEL
+};
+#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
+
+static void ip__resolve_ams(struct machine *self, struct thread *thread,
+                           struct addr_map_symbol *ams,
+                           u64 ip)
+{
+       struct addr_location al;
+       size_t i;
+       u8 m;
+
+       memset(&al, 0, sizeof(al));
+
+       for (i = 0; i < NCPUMODES; i++) {
+               m = cpumodes[i];
+               /*
+                * We cannot use the header.misc hint to determine whether a
+                * branch stack address is user, kernel, guest, hypervisor.
+                * Branches may straddle the kernel/user/hypervisor boundaries.
+                * Thus, we have to try consecutively until we find a match
+                * or else, the symbol is unknown
+                */
+               thread__find_addr_location(thread, self, m, MAP__FUNCTION,
+                               ip, &al, NULL);
+               if (al.sym)
+                       goto found;
+       }
+found:
+       ams->addr = ip;
+       ams->al_addr = al.addr;
+       ams->sym = al.sym;
+       ams->map = al.map;
+}
+
+struct branch_info *machine__resolve_bstack(struct machine *self,
+                                           struct thread *thr,
+                                           struct branch_stack *bs)
+{
+       struct branch_info *bi;
+       unsigned int i;
+
+       bi = calloc(bs->nr, sizeof(struct branch_info));
+       if (!bi)
+               return NULL;
+
+       for (i = 0; i < bs->nr; i++) {
+               ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to);
+               ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from);
+               bi[i].flags = bs->entries[i].flags;
+       }
+       return bi;
+}
+
+int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
+                              struct thread *thread,
+                              struct ip_callchain *chain,
+                              struct symbol **parent)
 {
        u8 cpumode = PERF_RECORD_MISC_USER;
        unsigned int i;
        int err;
 
-       callchain_cursor_reset(&self->callchain_cursor);
+       callchain_cursor_reset(&evsel->hists.callchain_cursor);
 
        for (i = 0; i < chain->nr; i++) {
                u64 ip;
@@ -252,7 +324,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
 
                al.filtered = false;
                thread__find_addr_location(thread, self, cpumode,
-                               MAP__FUNCTION, thread->pid, ip, &al, NULL);
+                                          MAP__FUNCTION, ip, &al, NULL);
                if (al.sym != NULL) {
                        if (sort__has_parent && !*parent &&
                            symbol__match_parent_regex(al.sym))
@@ -261,7 +333,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
                                break;
                }
 
-               err = callchain_cursor_append(&self->callchain_cursor,
+               err = callchain_cursor_append(&evsel->hists.callchain_cursor,
                                              ip, al.map, al.sym);
                if (err)
                        return err;
@@ -270,75 +342,91 @@ int perf_session__resolve_callchain(struct perf_session *self,
        return 0;
 }
 
-static int process_event_synth_stub(union perf_event *event __used,
-                                   struct perf_session *session __used)
+static int process_event_synth_tracing_data_stub(union perf_event *event __used,
+                                                struct perf_session *session __used)
 {
        dump_printf(": unhandled!\n");
        return 0;
 }
 
-static int process_event_sample_stub(union perf_event *event __used,
+static int process_event_synth_attr_stub(union perf_event *event __used,
+                                        struct perf_evlist **pevlist __used)
+{
+       dump_printf(": unhandled!\n");
+       return 0;
+}
+
+static int process_event_sample_stub(struct perf_tool *tool __used,
+                                    union perf_event *event __used,
                                     struct perf_sample *sample __used,
                                     struct perf_evsel *evsel __used,
-                                    struct perf_session *session __used)
+                                    struct machine *machine __used)
 {
        dump_printf(": unhandled!\n");
        return 0;
 }
 
-static int process_event_stub(union perf_event *event __used,
+static int process_event_stub(struct perf_tool *tool __used,
+                             union perf_event *event __used,
                              struct perf_sample *sample __used,
-                             struct perf_session *session __used)
+                             struct machine *machine __used)
+{
+       dump_printf(": unhandled!\n");
+       return 0;
+}
+
+static int process_finished_round_stub(struct perf_tool *tool __used,
+                                      union perf_event *event __used,
+                                      struct perf_session *perf_session __used)
 {
        dump_printf(": unhandled!\n");
        return 0;
 }
 
-static int process_finished_round_stub(union perf_event *event __used,
-                                      struct perf_session *session __used,
-                                      struct perf_event_ops *ops __used)
+static int process_event_type_stub(struct perf_tool *tool __used,
+                                  union perf_event *event __used)
 {
        dump_printf(": unhandled!\n");
        return 0;
 }
 
-static int process_finished_round(union perf_event *event,
-                                 struct perf_session *session,
-                                 struct perf_event_ops *ops);
-
-static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
-{
-       if (handler->sample == NULL)
-               handler->sample = process_event_sample_stub;
-       if (handler->mmap == NULL)
-               handler->mmap = process_event_stub;
-       if (handler->comm == NULL)
-               handler->comm = process_event_stub;
-       if (handler->fork == NULL)
-               handler->fork = process_event_stub;
-       if (handler->exit == NULL)
-               handler->exit = process_event_stub;
-       if (handler->lost == NULL)
-               handler->lost = perf_event__process_lost;
-       if (handler->read == NULL)
-               handler->read = process_event_stub;
-       if (handler->throttle == NULL)
-               handler->throttle = process_event_stub;
-       if (handler->unthrottle == NULL)
-               handler->unthrottle = process_event_stub;
-       if (handler->attr == NULL)
-               handler->attr = process_event_synth_stub;
-       if (handler->event_type == NULL)
-               handler->event_type = process_event_synth_stub;
-       if (handler->tracing_data == NULL)
-               handler->tracing_data = process_event_synth_stub;
-       if (handler->build_id == NULL)
-               handler->build_id = process_event_synth_stub;
-       if (handler->finished_round == NULL) {
-               if (handler->ordered_samples)
-                       handler->finished_round = process_finished_round;
+static int process_finished_round(struct perf_tool *tool,
+                                 union perf_event *event,
+                                 struct perf_session *session);
+
+static void perf_tool__fill_defaults(struct perf_tool *tool)
+{
+       if (tool->sample == NULL)
+               tool->sample = process_event_sample_stub;
+       if (tool->mmap == NULL)
+               tool->mmap = process_event_stub;
+       if (tool->comm == NULL)
+               tool->comm = process_event_stub;
+       if (tool->fork == NULL)
+               tool->fork = process_event_stub;
+       if (tool->exit == NULL)
+               tool->exit = process_event_stub;
+       if (tool->lost == NULL)
+               tool->lost = perf_event__process_lost;
+       if (tool->read == NULL)
+               tool->read = process_event_sample_stub;
+       if (tool->throttle == NULL)
+               tool->throttle = process_event_stub;
+       if (tool->unthrottle == NULL)
+               tool->unthrottle = process_event_stub;
+       if (tool->attr == NULL)
+               tool->attr = process_event_synth_attr_stub;
+       if (tool->event_type == NULL)
+               tool->event_type = process_event_type_stub;
+       if (tool->tracing_data == NULL)
+               tool->tracing_data = process_event_synth_tracing_data_stub;
+       if (tool->build_id == NULL)
+               tool->build_id = process_finished_round_stub;
+       if (tool->finished_round == NULL) {
+               if (tool->ordered_samples)
+                       tool->finished_round = process_finished_round;
                else
-                       handler->finished_round = process_finished_round_stub;
+                       tool->finished_round = process_finished_round_stub;
        }
 }
 
@@ -470,11 +558,11 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
 static int perf_session_deliver_event(struct perf_session *session,
                                      union perf_event *event,
                                      struct perf_sample *sample,
-                                     struct perf_event_ops *ops,
+                                     struct perf_tool *tool,
                                      u64 file_offset);
 
 static void flush_sample_queue(struct perf_session *s,
-                              struct perf_event_ops *ops)
+                              struct perf_tool *tool)
 {
        struct ordered_samples *os = &s->ordered_samples;
        struct list_head *head = &os->samples;
@@ -485,7 +573,7 @@ static void flush_sample_queue(struct perf_session *s,
        unsigned idx = 0, progress_next = os->nr_samples / 16;
        int ret;
 
-       if (!ops->ordered_samples || !limit)
+       if (!tool->ordered_samples || !limit)
                return;
 
        list_for_each_entry_safe(iter, tmp, head, list) {
@@ -496,7 +584,7 @@ static void flush_sample_queue(struct perf_session *s,
                if (ret)
                        pr_err("Can't parse sample, err = %d\n", ret);
                else
-                       perf_session_deliver_event(s, iter->event, &sample, ops,
+                       perf_session_deliver_event(s, iter->event, &sample, tool,
                                                   iter->file_offset);
 
                os->last_flush = iter->timestamp;
@@ -558,11 +646,11 @@ static void flush_sample_queue(struct perf_session *s,
  *      Flush every events below timestamp 7
  *      etc...
  */
-static int process_finished_round(union perf_event *event __used,
-                                 struct perf_session *session,
-                                 struct perf_event_ops *ops)
+static int process_finished_round(struct perf_tool *tool,
+                                 union perf_event *event __used,
+                                 struct perf_session *session)
 {
-       flush_sample_queue(session, ops);
+       flush_sample_queue(session, tool);
        session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
 
        return 0;
@@ -668,6 +756,18 @@ static void callchain__printf(struct perf_sample *sample)
                       i, sample->callchain->ips[i]);
 }
 
+static void branch_stack__printf(struct perf_sample *sample)
+{
+       uint64_t i;
+
+       printf("... branch stack: nr:%" PRIu64 "\n", sample->branch_stack->nr);
+
+       for (i = 0; i < sample->branch_stack->nr; i++)
+               printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 "\n",
+                       i, sample->branch_stack->entries[i].from,
+                       sample->branch_stack->entries[i].to);
+}
+
 static void perf_session__print_tstamp(struct perf_session *session,
                                       union perf_event *event,
                                       struct perf_sample *sample)
@@ -715,15 +815,39 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
 
        if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
                callchain__printf(sample);
+
+       if (session->sample_type & PERF_SAMPLE_BRANCH_STACK)
+               branch_stack__printf(sample);
+}
+
+static struct machine *
+       perf_session__find_machine_for_cpumode(struct perf_session *session,
+                                              union perf_event *event)
+{
+       const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+
+       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
+               u32 pid;
+
+               if (event->header.type == PERF_RECORD_MMAP)
+                       pid = event->mmap.pid;
+               else
+                       pid = event->ip.pid;
+
+               return perf_session__find_machine(session, pid);
+       }
+
+       return perf_session__find_host_machine(session);
 }
 
 static int perf_session_deliver_event(struct perf_session *session,
                                      union perf_event *event,
                                      struct perf_sample *sample,
-                                     struct perf_event_ops *ops,
+                                     struct perf_tool *tool,
                                      u64 file_offset)
 {
        struct perf_evsel *evsel;
+       struct machine *machine;
 
        dump_event(session, event, file_offset, sample);
 
@@ -745,6 +869,8 @@ static int perf_session_deliver_event(struct perf_session *session,
                hists__inc_nr_events(&evsel->hists, event->header.type);
        }
 
+       machine = perf_session__find_machine_for_cpumode(session, event);
+
        switch (event->header.type) {
        case PERF_RECORD_SAMPLE:
                dump_sample(session, event, sample);
@@ -752,23 +878,29 @@ static int perf_session_deliver_event(struct perf_session *session,
                        ++session->hists.stats.nr_unknown_id;
                        return -1;
                }
-               return ops->sample(event, sample, evsel, session);
+               if (machine == NULL) {
+                       ++session->hists.stats.nr_unprocessable_samples;
+                       return -1;
+               }
+               return tool->sample(tool, event, sample, evsel, machine);
        case PERF_RECORD_MMAP:
-               return ops->mmap(event, sample, session);
+               return tool->mmap(tool, event, sample, machine);
        case PERF_RECORD_COMM:
-               return ops->comm(event, sample, session);
+               return tool->comm(tool, event, sample, machine);
        case PERF_RECORD_FORK:
-               return ops->fork(event, sample, session);
+               return tool->fork(tool, event, sample, machine);
        case PERF_RECORD_EXIT:
-               return ops->exit(event, sample, session);
+               return tool->exit(tool, event, sample, machine);
        case PERF_RECORD_LOST:
-               return ops->lost(event, sample, session);
+               if (tool->lost == perf_event__process_lost)
+                       session->hists.stats.total_lost += event->lost.lost;
+               return tool->lost(tool, event, sample, machine);
        case PERF_RECORD_READ:
-               return ops->read(event, sample, session);
+               return tool->read(tool, event, sample, evsel, machine);
        case PERF_RECORD_THROTTLE:
-               return ops->throttle(event, sample, session);
+               return tool->throttle(tool, event, sample, machine);
        case PERF_RECORD_UNTHROTTLE:
-               return ops->unthrottle(event, sample, session);
+               return tool->unthrottle(tool, event, sample, machine);
        default:
                ++session->hists.stats.nr_unknown_events;
                return -1;
@@ -792,24 +924,29 @@ static int perf_session__preprocess_sample(struct perf_session *session,
 }
 
 static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
-                                           struct perf_event_ops *ops, u64 file_offset)
+                                           struct perf_tool *tool, u64 file_offset)
 {
+       int err;
+
        dump_event(session, event, file_offset, NULL);
 
        /* These events are processed right away */
        switch (event->header.type) {
        case PERF_RECORD_HEADER_ATTR:
-               return ops->attr(event, session);
+               err = tool->attr(event, &session->evlist);
+               if (err == 0)
+                       perf_session__update_sample_type(session);
+               return err;
        case PERF_RECORD_HEADER_EVENT_TYPE:
-               return ops->event_type(event, session);
+               return tool->event_type(tool, event);
        case PERF_RECORD_HEADER_TRACING_DATA:
                /* setup for reading amidst mmap */
                lseek(session->fd, file_offset, SEEK_SET);
-               return ops->tracing_data(event, session);
+               return tool->tracing_data(event, session);
        case PERF_RECORD_HEADER_BUILD_ID:
-               return ops->build_id(event, session);
+               return tool->build_id(tool, event, session);
        case PERF_RECORD_FINISHED_ROUND:
-               return ops->finished_round(event, session, ops);
+               return tool->finished_round(tool, event, session);
        default:
                return -EINVAL;
        }
@@ -817,7 +954,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
 
 static int perf_session__process_event(struct perf_session *session,
                                       union perf_event *event,
-                                      struct perf_event_ops *ops,
+                                      struct perf_tool *tool,
                                       u64 file_offset)
 {
        struct perf_sample sample;
@@ -833,7 +970,7 @@ static int perf_session__process_event(struct perf_session *session,
        hists__inc_nr_events(&session->hists, event->header.type);
 
        if (event->header.type >= PERF_RECORD_USER_TYPE_START)
-               return perf_session__process_user_event(session, event, ops, file_offset);
+               return perf_session__process_user_event(session, event, tool, file_offset);
 
        /*
         * For all kernel events we get the sample data
@@ -846,14 +983,14 @@ static int perf_session__process_event(struct perf_session *session,
        if (perf_session__preprocess_sample(session, event, &sample))
                return 0;
 
-       if (ops->ordered_samples) {
+       if (tool->ordered_samples) {
                ret = perf_session_queue_event(session, event, &sample,
                                               file_offset);
                if (ret != -ETIME)
                        return ret;
        }
 
-       return perf_session_deliver_event(session, event, &sample, ops,
+       return perf_session_deliver_event(session, event, &sample, tool,
                                          file_offset);
 }
 
@@ -882,9 +1019,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
 }
 
 static void perf_session__warn_about_errors(const struct perf_session *session,
-                                           const struct perf_event_ops *ops)
+                                           const struct perf_tool *tool)
 {
-       if (ops->lost == perf_event__process_lost &&
+       if (tool->lost == perf_event__process_lost &&
            session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
                ui__warning("Processed %d events and lost %d chunks!\n\n"
                            "Check IO/CPU overload!\n\n",
@@ -913,13 +1050,19 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
                            session->hists.stats.nr_invalid_chains,
                            session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
        }
+
+       if (session->hists.stats.nr_unprocessable_samples != 0) {
+               ui__warning("%u unprocessable samples recorded.\n"
+                           "Do you have a KVM guest running and not using 'perf kvm'?\n",
+                           session->hists.stats.nr_unprocessable_samples);
+       }
 }
 
 #define session_done() (*(volatile int *)(&session_done))
 volatile int session_done;
 
 static int __perf_session__process_pipe_events(struct perf_session *self,
-                                              struct perf_event_ops *ops)
+                                              struct perf_tool *tool)
 {
        union perf_event event;
        uint32_t size;
@@ -928,7 +1071,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
        int err;
        void *p;
 
-       perf_event_ops__fill_defaults(ops);
+       perf_tool__fill_defaults(tool);
 
        head = 0;
 more:
@@ -964,8 +1107,7 @@ more:
                }
        }
 
-       if (size == 0 ||
-           (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
+       if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) {
                dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
                            head, event.header.size, event.header.type);
                /*
@@ -988,7 +1130,7 @@ more:
 done:
        err = 0;
 out_err:
-       perf_session__warn_about_errors(self, ops);
+       perf_session__warn_about_errors(self, tool);
        perf_session_free_sample_buffers(self);
        return err;
 }
@@ -1019,7 +1161,7 @@ fetch_mmaped_event(struct perf_session *session,
 
 int __perf_session__process_events(struct perf_session *session,
                                   u64 data_offset, u64 data_size,
-                                  u64 file_size, struct perf_event_ops *ops)
+                                  u64 file_size, struct perf_tool *tool)
 {
        u64 head, page_offset, file_offset, file_pos, progress_next;
        int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1028,7 +1170,7 @@ int __perf_session__process_events(struct perf_session *session,
        union perf_event *event;
        uint32_t size;
 
-       perf_event_ops__fill_defaults(ops);
+       perf_tool__fill_defaults(tool);
 
        page_size = sysconf(_SC_PAGESIZE);
 
@@ -1083,7 +1225,7 @@ more:
        size = event->header.size;
 
        if (size == 0 ||
-           perf_session__process_event(session, event, ops, file_pos) < 0) {
+           perf_session__process_event(session, event, tool, file_pos) < 0) {
                dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
                            file_offset + head, event->header.size,
                            event->header.type);
@@ -1112,15 +1254,15 @@ more:
        err = 0;
        /* do the final flush for ordered samples */
        session->ordered_samples.next_flush = ULLONG_MAX;
-       flush_sample_queue(session, ops);
+       flush_sample_queue(session, tool);
 out_err:
-       perf_session__warn_about_errors(session, ops);
+       perf_session__warn_about_errors(session, tool);
        perf_session_free_sample_buffers(session);
        return err;
 }
 
 int perf_session__process_events(struct perf_session *self,
-                                struct perf_event_ops *ops)
+                                struct perf_tool *tool)
 {
        int err;
 
@@ -1131,9 +1273,9 @@ int perf_session__process_events(struct perf_session *self,
                err = __perf_session__process_events(self,
                                                     self->header.data_offset,
                                                     self->header.data_size,
-                                                    self->size, ops);
+                                                    self->size, tool);
        else
-               err = __perf_session__process_pipe_events(self, ops);
+               err = __perf_session__process_pipe_events(self, tool);
 
        return err;
 }
@@ -1148,9 +1290,8 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
        return true;
 }
 
-int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
-                                            const char *symbol_name,
-                                            u64 addr)
+int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
+                                    const char *symbol_name, u64 addr)
 {
        char *bracket;
        enum map_type i;
@@ -1242,17 +1383,15 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
        return NULL;
 }
 
-void perf_session__print_ip(union perf_event *event,
-                           struct perf_sample *sample,
-                           struct perf_session *session,
-                           int print_sym, int print_dso)
+void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
+                         struct machine *machine, struct perf_evsel *evsel,
+                         int print_sym, int print_dso, int print_symoffset)
 {
        struct addr_location al;
-       const char *symname, *dsoname;
-       struct callchain_cursor *cursor = &session->callchain_cursor;
+       struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
        struct callchain_cursor_node *node;
 
-       if (perf_event__preprocess_sample(event, session, &al, sample,
+       if (perf_event__preprocess_sample(event, machine, &al, sample,
                                          NULL) < 0) {
                error("problem processing %d event, skipping it.\n",
                        event->header.type);
@@ -1261,7 +1400,7 @@ void perf_session__print_ip(union perf_event *event,
 
        if (symbol_conf.use_callchain && sample->callchain) {
 
-               if (perf_session__resolve_callchain(session, al.thread,
+               if (machine__resolve_callchain(machine, evsel, al.thread,
                                                sample->callchain, NULL) != 0) {
                        if (verbose)
                                error("Failed to resolve callchain. Skipping\n");
@@ -1276,20 +1415,13 @@ void perf_session__print_ip(union perf_event *event,
 
                        printf("\t%16" PRIx64, node->ip);
                        if (print_sym) {
-                               if (node->sym && node->sym->name)
-                                       symname = node->sym->name;
-                               else
-                                       symname = "";
-
-                               printf(" %s", symname);
+                               printf(" ");
+                               symbol__fprintf_symname(node->sym, stdout);
                        }
                        if (print_dso) {
-                               if (node->map && node->map->dso && node->map->dso->name)
-                                       dsoname = node->map->dso->name;
-                               else
-                                       dsoname = "";
-
-                               printf(" (%s)", dsoname);
+                               printf(" (");
+                               map__fprintf_dsoname(al.map, stdout);
+                               printf(")");
                        }
                        printf("\n");
 
@@ -1299,21 +1431,18 @@ void perf_session__print_ip(union perf_event *event,
        } else {
                printf("%16" PRIx64, sample->ip);
                if (print_sym) {
-                       if (al.sym && al.sym->name)
-                               symname = al.sym->name;
+                       printf(" ");
+                       if (print_symoffset)
+                               symbol__fprintf_symname_offs(al.sym, &al,
+                                                            stdout);
                        else
-                               symname = "";
-
-                       printf(" %s", symname);
+                               symbol__fprintf_symname(al.sym, stdout);
                }
 
                if (print_dso) {
-                       if (al.map && al.map->dso && al.map->dso->name)
-                               dsoname = al.map->dso->name;
-                       else
-                               dsoname = "";
-
-                       printf(" (%s)", dsoname);
+                       printf(" (");
+                       map__fprintf_dsoname(al.map, stdout);
+                       printf(")");
                }
        }
 }
@@ -1339,6 +1468,10 @@ int perf_session__cpu_bitmap(struct perf_session *session,
        }
 
        map = cpu_map__new(cpu_list);
+       if (map == NULL) {
+               pr_err("Invalid cpu_list\n");
+               return -1;
+       }
 
        for (i = 0; i < map->nr; i++) {
                int cpu = map->map[i];