Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Mar 2010 23:52:46 +0000 (16:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Mar 2010 23:52:46 +0000 (16:52 -0700)
* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (35 commits)
  perf: Fix unexported generic perf_arch_fetch_caller_regs
  perf record: Don't try to find buildids in a zero sized file
  perf: export perf_trace_regs and perf_arch_fetch_caller_regs
  perf, x86: Fix hw_perf_enable() event assignment
  perf, ppc: Fix compile error due to new cpu notifiers
  perf: Make the install relative to DESTDIR if specified
  kprobes: Calculate the index correctly when freeing the out-of-line execution slot
  perf tools: Fix sparse CPU numbering related bugs
  perf_event: Fix oops triggered by cpu offline/online
  perf: Drop the obsolete profile naming for trace events
  perf: Take a hot regs snapshot for trace events
  perf: Introduce new perf_fetch_caller_regs() for hot regs snapshot
  perf/x86-64: Use frame pointer to walk on irq and process stacks
  lockdep: Move lock events under lockdep recursion protection
  perf report: Print the map table just after samples for which no map was found
  perf report: Add multiple event support
  perf session: Change perf_session post processing functions to take histogram tree
  perf session: Add storage for seperating event types in report
  perf session: Change add_hist_entry to take the tree root instead of session
  perf record: Add ID and to recorded event data when recording multiple events
  ...

1  2 
include/linux/syscalls.h
include/trace/ftrace.h
kernel/lockdep.c
kernel/trace/trace_event_perf.c
tools/perf/util/hist.c

diff --combined include/linux/syscalls.h
@@@ -23,7 -23,6 +23,7 @@@ struct kexec_segment
  struct linux_dirent;
  struct linux_dirent64;
  struct list_head;
 +struct mmap_arg_struct;
  struct msgbuf;
  struct msghdr;
  struct mmsghdr;
@@@ -31,13 -30,10 +31,13 @@@ struct msqid_ds
  struct new_utsname;
  struct nfsctl_arg;
  struct __old_kernel_stat;
 +struct oldold_utsname;
 +struct old_utsname;
  struct pollfd;
  struct rlimit;
  struct rusage;
  struct sched_param;
 +struct sel_arg_struct;
  struct semaphore;
  struct sembuf;
  struct shmid_ds;
@@@ -105,18 -101,18 +105,18 @@@ struct perf_event_attr
  
  #ifdef CONFIG_PERF_EVENTS
  
- #define TRACE_SYS_ENTER_PROFILE_INIT(sname)                                  \
-       .profile_enable = prof_sysenter_enable,                                \
-       .profile_disable = prof_sysenter_disable,
+ #define TRACE_SYS_ENTER_PERF_INIT(sname)                                     \
+       .perf_event_enable = perf_sysenter_enable,                             \
+       .perf_event_disable = perf_sysenter_disable,
  
- #define TRACE_SYS_EXIT_PROFILE_INIT(sname)                                   \
-       .profile_enable = prof_sysexit_enable,                                 \
-       .profile_disable = prof_sysexit_disable,
+ #define TRACE_SYS_EXIT_PERF_INIT(sname)                                              \
+       .perf_event_enable = perf_sysexit_enable,                              \
+       .perf_event_disable = perf_sysexit_disable,
  #else
- #define TRACE_SYS_ENTER_PROFILE(sname)
- #define TRACE_SYS_ENTER_PROFILE_INIT(sname)
- #define TRACE_SYS_EXIT_PROFILE(sname)
- #define TRACE_SYS_EXIT_PROFILE_INIT(sname)
+ #define TRACE_SYS_ENTER_PERF(sname)
+ #define TRACE_SYS_ENTER_PERF_INIT(sname)
+ #define TRACE_SYS_EXIT_PERF(sname)
+ #define TRACE_SYS_EXIT_PERF_INIT(sname)
  #endif /* CONFIG_PERF_EVENTS */
  
  #ifdef CONFIG_FTRACE_SYSCALLS
                .regfunc                = reg_event_syscall_enter,      \
                .unregfunc              = unreg_event_syscall_enter,    \
                .data                   = (void *)&__syscall_meta_##sname,\
-               TRACE_SYS_ENTER_PROFILE_INIT(sname)                     \
+               TRACE_SYS_ENTER_PERF_INIT(sname)                        \
        }
  
  #define SYSCALL_TRACE_EXIT_EVENT(sname)                                       \
                .regfunc                = reg_event_syscall_exit,       \
                .unregfunc              = unreg_event_syscall_exit,     \
                .data                   = (void *)&__syscall_meta_##sname,\
-               TRACE_SYS_EXIT_PROFILE_INIT(sname)                      \
+               TRACE_SYS_EXIT_PERF_INIT(sname)                 \
        }
  
  #define SYSCALL_METADATA(sname, nb)                           \
@@@ -642,7 -638,6 +642,7 @@@ asmlinkage long sys_poll(struct pollfd 
                                long timeout);
  asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
                        fd_set __user *exp, struct timeval __user *tvp);
 +asmlinkage long sys_old_select(struct sel_arg_struct __user *arg);
  asmlinkage long sys_epoll_create(int size);
  asmlinkage long sys_epoll_create1(int flags);
  asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
@@@ -657,8 -652,6 +657,8 @@@ asmlinkage long sys_gethostname(char __
  asmlinkage long sys_sethostname(char __user *name, int len);
  asmlinkage long sys_setdomainname(char __user *name, int len);
  asmlinkage long sys_newuname(struct new_utsname __user *name);
 +asmlinkage long sys_uname(struct old_utsname __user *);
 +asmlinkage long sys_olduname(struct oldold_utsname __user *);
  
  asmlinkage long sys_getrlimit(unsigned int resource,
                                struct rlimit __user *rlim);
@@@ -688,8 -681,6 +688,8 @@@ asmlinkage long sys_shmat(int shmid, ch
  asmlinkage long sys_shmget(key_t key, size_t size, int flag);
  asmlinkage long sys_shmdt(char __user *shmaddr);
  asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
 +asmlinkage long sys_ipc(unsigned int call, int first, int second,
 +              unsigned long third, void __user *ptr, long fifth);
  
  asmlinkage long sys_mq_open(const char __user *name, int oflag, mode_t mode, struct mq_attr __user *attr);
  asmlinkage long sys_mq_unlink(const char __user *name);
@@@ -845,6 -836,4 +845,6 @@@ asmlinkage long sys_perf_event_open
  asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
                        unsigned long prot, unsigned long flags,
                        unsigned long fd, unsigned long pgoff);
 +asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
 +
  #endif
diff --combined include/trace/ftrace.h
@@@ -401,18 -401,18 +401,18 @@@ static inline notrace int ftrace_get_of
  #undef DEFINE_EVENT
  #define DEFINE_EVENT(template, name, proto, args)                     \
                                                                        \
- static void ftrace_profile_##name(proto);                             \
+ static void perf_trace_##name(proto);                                 \
                                                                        \
  static notrace int                                                    \
ftrace_profile_enable_##name(struct ftrace_event_call *unused)                \
perf_trace_enable_##name(struct ftrace_event_call *unused)            \
  {                                                                     \
-       return register_trace_##name(ftrace_profile_##name);            \
+       return register_trace_##name(perf_trace_##name);                \
  }                                                                     \
                                                                        \
  static notrace void                                                   \
ftrace_profile_disable_##name(struct ftrace_event_call *unused)               \
perf_trace_disable_##name(struct ftrace_event_call *unused)           \
  {                                                                     \
-       unregister_trace_##name(ftrace_profile_##name);                 \
+       unregister_trace_##name(perf_trace_##name);                     \
  }
  
  #undef DEFINE_EVENT_PRINT
  
  #ifdef CONFIG_PERF_EVENTS
  
- #define _TRACE_PROFILE_INIT(call)                                     \
-       .profile_enable = ftrace_profile_enable_##call,                 \
-       .profile_disable = ftrace_profile_disable_##call,
+ #define _TRACE_PERF_INIT(call)                                                \
+       .perf_event_enable = perf_trace_enable_##call,                  \
+       .perf_event_disable = perf_trace_disable_##call,
  
  #else
- #define _TRACE_PROFILE_INIT(call)
+ #define _TRACE_PERF_INIT(call)
  #endif /* CONFIG_PERF_EVENTS */
  
  #undef __entry
@@@ -638,7 -638,7 +638,7 @@@ __attribute__((section("_ftrace_events"
        .unregfunc              = ftrace_raw_unreg_event_##call,        \
        .print_fmt              = print_fmt_##template,                 \
        .define_fields          = ftrace_define_fields_##template,      \
-       _TRACE_PROFILE_INIT(call)                                       \
+       _TRACE_PERF_INIT(call)                                  \
  }
  
  #undef DEFINE_EVENT_PRINT
@@@ -657,18 -657,18 +657,18 @@@ __attribute__((section("_ftrace_events"
        .unregfunc              = ftrace_raw_unreg_event_##call,        \
        .print_fmt              = print_fmt_##call,                     \
        .define_fields          = ftrace_define_fields_##template,      \
-       _TRACE_PROFILE_INIT(call)                                       \
+       _TRACE_PERF_INIT(call)                                  \
  }
  
  #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
  
  /*
-  * Define the insertion callback to profile events
+  * Define the insertion callback to perf events
   *
   * The job is very similar to ftrace_raw_event_<call> except that we don't
   * insert in the ring buffer but in a perf counter.
   *
-  * static void ftrace_profile_<call>(proto)
+  * static void ftrace_perf_<call>(proto)
   * {
   *    struct ftrace_data_offsets_<call> __maybe_unused __data_offsets;
   *    struct ftrace_event_call *event_call = &event_<call>;
   *    __cpu = smp_processor_id();
   *
   *    if (in_nmi())
 - *            trace_buf = rcu_dereference(perf_trace_buf_nmi);
 + *            trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
   *    else
 - *            trace_buf = rcu_dereference(perf_trace_buf);
 + *            trace_buf = rcu_dereference_sched(perf_trace_buf);
   *
   *    if (!trace_buf)
   *            goto end;
  #undef DECLARE_EVENT_CLASS
  #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)        \
  static notrace void                                                   \
ftrace_profile_templ_##call(struct ftrace_event_call *event_call,     \
perf_trace_templ_##call(struct ftrace_event_call *event_call,         \
                            proto)                                      \
  {                                                                     \
        struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
        struct ftrace_raw_##call *entry;                                \
        u64 __addr = 0, __count = 1;                                    \
        unsigned long irq_flags;                                        \
+       struct pt_regs *__regs;                                         \
        int __entry_size;                                               \
        int __data_size;                                                \
        int rctx;                                                       \
                             sizeof(u64));                              \
        __entry_size -= sizeof(u32);                                    \
                                                                        \
-       if (WARN_ONCE(__entry_size > FTRACE_MAX_PROFILE_SIZE,           \
+       if (WARN_ONCE(__entry_size > PERF_MAX_TRACE_SIZE,               \
                      "profile buffer not large enough"))               \
                return;                                                 \
-       entry = (struct ftrace_raw_##call *)ftrace_perf_buf_prepare(    \
+       entry = (struct ftrace_raw_##call *)perf_trace_buf_prepare(     \
                __entry_size, event_call->id, &rctx, &irq_flags);       \
        if (!entry)                                                     \
                return;                                                 \
                                                                        \
        { assign; }                                                     \
                                                                        \
-       ftrace_perf_buf_submit(entry, __entry_size, rctx, __addr,       \
-                              __count, irq_flags);                     \
+       __regs = &__get_cpu_var(perf_trace_regs);                       \
+       perf_fetch_caller_regs(__regs, 2);                              \
+                                                                       \
+       perf_trace_buf_submit(entry, __entry_size, rctx, __addr,        \
+                              __count, irq_flags, __regs);             \
  }
  
  #undef DEFINE_EVENT
  #define DEFINE_EVENT(template, call, proto, args)             \
- static notrace void ftrace_profile_##call(proto)              \
+ static notrace void perf_trace_##call(proto)                  \
  {                                                             \
        struct ftrace_event_call *event_call = &event_##call;   \
                                                                \
-       ftrace_profile_templ_##template(event_call, args);      \
+       perf_trace_templ_##template(event_call, args);          \
  }
  
  #undef DEFINE_EVENT_PRINT
diff --combined kernel/lockdep.c
@@@ -3211,8 -3211,6 +3211,6 @@@ void lock_acquire(struct lockdep_map *l
  {
        unsigned long flags;
  
-       trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip);
        if (unlikely(current->lockdep_recursion))
                return;
  
        check_flags(flags);
  
        current->lockdep_recursion = 1;
+       trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip);
        __lock_acquire(lock, subclass, trylock, read, check,
                       irqs_disabled_flags(flags), nest_lock, ip, 0);
        current->lockdep_recursion = 0;
@@@ -3232,14 -3231,13 +3231,13 @@@ void lock_release(struct lockdep_map *l
  {
        unsigned long flags;
  
-       trace_lock_release(lock, nested, ip);
        if (unlikely(current->lockdep_recursion))
                return;
  
        raw_local_irq_save(flags);
        check_flags(flags);
        current->lockdep_recursion = 1;
+       trace_lock_release(lock, nested, ip);
        __lock_release(lock, nested, ip);
        current->lockdep_recursion = 0;
        raw_local_irq_restore(flags);
@@@ -3413,8 -3411,6 +3411,6 @@@ void lock_contended(struct lockdep_map 
  {
        unsigned long flags;
  
-       trace_lock_contended(lock, ip);
        if (unlikely(!lock_stat))
                return;
  
        raw_local_irq_save(flags);
        check_flags(flags);
        current->lockdep_recursion = 1;
+       trace_lock_contended(lock, ip);
        __lock_contended(lock, ip);
        current->lockdep_recursion = 0;
        raw_local_irq_restore(flags);
@@@ -3822,7 -3819,6 +3819,7 @@@ void lockdep_rcu_dereference(const cha
        printk("%s:%d invoked rcu_dereference_check() without protection!\n",
                        file, line);
        printk("\nother info that might help us debug this:\n\n");
 +      printk("\nrcu_scheduler_active = %d, debug_locks = %d\n", rcu_scheduler_active, debug_locks);
        lockdep_print_held_locks(curr);
        printk("\nstack backtrace:\n");
        dump_stack();
@@@ -1,32 -1,36 +1,36 @@@
  /*
-  * trace event based perf counter profiling
+  * trace event based perf event profiling/tracing
   *
   * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com>
-  *
+  * Copyright (C) 2009-2010 Frederic Weisbecker <fweisbec@gmail.com>
   */
  
  #include <linux/module.h>
  #include <linux/kprobes.h>
  #include "trace.h"
  
+ DEFINE_PER_CPU(struct pt_regs, perf_trace_regs);
+ EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_regs);
+ EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs);
  
  static char *perf_trace_buf;
  static char *perf_trace_buf_nmi;
  
- typedef typeof(char [FTRACE_MAX_PROFILE_SIZE]) perf_trace_t ;
+ typedef typeof(char [PERF_MAX_TRACE_SIZE]) perf_trace_t ;
  
  /* Count the events in use (per event id, not per instance) */
- static int    total_profile_count;
+ static int    total_ref_count;
  
- static int ftrace_profile_enable_event(struct ftrace_event_call *event)
+ static int perf_trace_event_enable(struct ftrace_event_call *event)
  {
        char *buf;
        int ret = -ENOMEM;
  
-       if (event->profile_count++ > 0)
+       if (event->perf_refcount++ > 0)
                return 0;
  
-       if (!total_profile_count) {
+       if (!total_ref_count) {
                buf = (char *)alloc_percpu(perf_trace_t);
                if (!buf)
                        goto fail_buf;
                rcu_assign_pointer(perf_trace_buf_nmi, buf);
        }
  
-       ret = event->profile_enable(event);
+       ret = event->perf_event_enable(event);
        if (!ret) {
-               total_profile_count++;
+               total_ref_count++;
                return 0;
        }
  
  fail_buf_nmi:
-       if (!total_profile_count) {
+       if (!total_ref_count) {
                free_percpu(perf_trace_buf_nmi);
                free_percpu(perf_trace_buf);
                perf_trace_buf_nmi = NULL;
                perf_trace_buf = NULL;
        }
  fail_buf:
-       event->profile_count--;
+       event->perf_refcount--;
  
        return ret;
  }
  
- int ftrace_profile_enable(int event_id)
+ int perf_trace_enable(int event_id)
  {
        struct ftrace_event_call *event;
        int ret = -EINVAL;
  
        mutex_lock(&event_mutex);
        list_for_each_entry(event, &ftrace_events, list) {
-               if (event->id == event_id && event->profile_enable &&
+               if (event->id == event_id && event->perf_event_enable &&
                    try_module_get(event->mod)) {
-                       ret = ftrace_profile_enable_event(event);
+                       ret = perf_trace_event_enable(event);
                        break;
                }
        }
        return ret;
  }
  
- static void ftrace_profile_disable_event(struct ftrace_event_call *event)
+ static void perf_trace_event_disable(struct ftrace_event_call *event)
  {
        char *buf, *nmi_buf;
  
-       if (--event->profile_count > 0)
+       if (--event->perf_refcount > 0)
                return;
  
-       event->profile_disable(event);
+       event->perf_event_disable(event);
  
-       if (!--total_profile_count) {
+       if (!--total_ref_count) {
                buf = perf_trace_buf;
                rcu_assign_pointer(perf_trace_buf, NULL);
  
        }
  }
  
- void ftrace_profile_disable(int event_id)
+ void perf_trace_disable(int event_id)
  {
        struct ftrace_event_call *event;
  
        mutex_lock(&event_mutex);
        list_for_each_entry(event, &ftrace_events, list) {
                if (event->id == event_id) {
-                       ftrace_profile_disable_event(event);
+                       perf_trace_event_disable(event);
                        module_put(event->mod);
                        break;
                }
        mutex_unlock(&event_mutex);
  }
  
- __kprobes void *ftrace_perf_buf_prepare(int size, unsigned short type,
-                                       int *rctxp, unsigned long *irq_flags)
+ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
+                                      int *rctxp, unsigned long *irq_flags)
  {
        struct trace_entry *entry;
        char *trace_buf, *raw_data;
        cpu = smp_processor_id();
  
        if (in_nmi())
 -              trace_buf = rcu_dereference(perf_trace_buf_nmi);
 +              trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
        else
 -              trace_buf = rcu_dereference(perf_trace_buf);
 +              trace_buf = rcu_dereference_sched(perf_trace_buf);
  
        if (!trace_buf)
                goto err;
@@@ -161,4 -165,4 +165,4 @@@ err_recursion
        local_irq_restore(*irq_flags);
        return NULL;
  }
- EXPORT_SYMBOL_GPL(ftrace_perf_buf_prepare);
+ EXPORT_SYMBOL_GPL(perf_trace_buf_prepare);
diff --combined tools/perf/util/hist.c
@@@ -12,12 -12,12 +12,12 @@@ struct callchain_param     callchain_param 
   * histogram, sorted on item, collects counts
   */
  
- struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
+ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
                                                  struct addr_location *al,
                                                  struct symbol *sym_parent,
                                                  u64 count, bool *hit)
  {
-       struct rb_node **p = &self->hists.rb_node;
+       struct rb_node **p = &hists->rb_node;
        struct rb_node *parent = NULL;
        struct hist_entry *he;
        struct hist_entry entry = {
@@@ -53,7 -53,7 +53,7 @@@
                return NULL;
        *he = entry;
        rb_link_node(&he->rb_node, parent, p);
-       rb_insert_color(&he->rb_node, &self->hists);
+       rb_insert_color(&he->rb_node, hists);
        *hit = false;
        return he;
  }
@@@ -130,7 -130,7 +130,7 @@@ static void collapse__insert_entry(stru
        rb_insert_color(&he->rb_node, root);
  }
  
- void perf_session__collapse_resort(struct perf_session *self)
+ void perf_session__collapse_resort(struct rb_root *hists)
  {
        struct rb_root tmp;
        struct rb_node *next;
                return;
  
        tmp = RB_ROOT;
-       next = rb_first(&self->hists);
+       next = rb_first(hists);
  
        while (next) {
                n = rb_entry(next, struct hist_entry, rb_node);
                next = rb_next(&n->rb_node);
  
-               rb_erase(&n->rb_node, &self->hists);
+               rb_erase(&n->rb_node, hists);
                collapse__insert_entry(&tmp, n);
        }
  
-       self->hists = tmp;
+       *hists = tmp;
  }
  
  /*
@@@ -183,7 -183,7 +183,7 @@@ static void perf_session__insert_output
        rb_insert_color(&he->rb_node, root);
  }
  
- void perf_session__output_resort(struct perf_session *self, u64 total_samples)
+ void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
  {
        struct rb_root tmp;
        struct rb_node *next;
                total_samples * (callchain_param.min_percent / 100);
  
        tmp = RB_ROOT;
-       next = rb_first(&self->hists);
+       next = rb_first(hists);
  
        while (next) {
                n = rb_entry(next, struct hist_entry, rb_node);
                next = rb_next(&n->rb_node);
  
-               rb_erase(&n->rb_node, &self->hists);
+               rb_erase(&n->rb_node, hists);
                perf_session__insert_output_hist_entry(&tmp, n,
                                                       min_callchain_hits);
        }
  
-       self->hists = tmp;
+       *hists = tmp;
  }
  
  static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@@ -321,7 -321,7 +321,7 @@@ static size_t __callchain__fprintf_grap
                        new_depth_mask &= ~(1 << (depth - 1));
  
                /*
 -               * But we keep the older depth mask for the line seperator
 +               * But we keep the older depth mask for the line separator
                 * to keep the level link until we reach the last child
                 */
                ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
@@@ -456,10 -456,10 +456,10 @@@ static size_t hist_entry_callchain__fpr
  }
  
  static size_t hist_entry__fprintf(struct hist_entry *self,
-                                 struct perf_session *session,
                                  struct perf_session *pair_session,
                                  bool show_displacement,
-                                 long displacement, FILE *fp)
+                                 long displacement, FILE *fp,
+                                 u64 session_total)
  {
        struct sort_entry *se;
        u64 count, total;
                total = pair_session->events_stats.total;
        } else {
                count = self->count;
-               total = session->events_stats.total;
+               total = session_total;
        }
  
        if (total)
  
                if (total > 0)
                        old_percent = (count * 100.0) / total;
-               if (session->events_stats.total > 0)
-                       new_percent = (self->count * 100.0) / session->events_stats.total;
+               if (session_total > 0)
+                       new_percent = (self->count * 100.0) / session_total;
  
                diff = new_percent - old_percent;
  
                        left_margin -= thread__comm_len(self->thread);
                }
  
-               hist_entry_callchain__fprintf(fp, self, session->events_stats.total,
+               hist_entry_callchain__fprintf(fp, self, session_total,
                                              left_margin);
        }
  
        return ret;
  }
  
- size_t perf_session__fprintf_hists(struct perf_session *self,
+ size_t perf_session__fprintf_hists(struct rb_root *hists,
                                   struct perf_session *pair,
-                                  bool show_displacement, FILE *fp)
+                                  bool show_displacement, FILE *fp,
+                                  u64 session_total)
  {
        struct sort_entry *se;
        struct rb_node *nd;
        fprintf(fp, "\n#\n");
  
  print_entries:
-       for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
  
                if (show_displacement) {
                                displacement = 0;
                        ++position;
                }
-               ret += hist_entry__fprintf(h, self, pair, show_displacement,
-                                          displacement, fp);
+               ret += hist_entry__fprintf(h, pair, show_displacement,
+                                          displacement, fp, session_total);
+               if (h->map == NULL && verbose > 1) {
+                       __map_groups__fprintf_maps(&h->thread->mg,
+                                                  MAP__FUNCTION, fp);
+                       fprintf(fp, "%.10s end\n", graph_dotted_line);
+               }
        }
  
        free(rem_sq_bracket);