Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorIngo Molnar <mingo@kernel.org>
Fri, 13 Apr 2012 07:47:04 +0000 (09:47 +0200)
committerIngo Molnar <mingo@kernel.org>
Fri, 13 Apr 2012 07:47:04 +0000 (09:47 +0200)
Pull various perf tooling fixes from Arnaldo Carvalho de Melo.

tools/perf/builtin-top.c
tools/perf/util/annotate.c
tools/perf/util/hist.c
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/session.c
tools/perf/util/ui/browsers/hists.c

index e3c63aef8efc6a334728ee9864c8243415c478be..8ef59f8262bb37a28c2e83724dbe62b88df349e7 100644 (file)
@@ -42,6 +42,7 @@
 #include "util/debug.h"
 
 #include <assert.h>
+#include <elf.h>
 #include <fcntl.h>
 
 #include <stdio.h>
@@ -59,6 +60,7 @@
 #include <sys/prctl.h>
 #include <sys/wait.h>
 #include <sys/uio.h>
+#include <sys/utsname.h>
 #include <sys/mman.h>
 
 #include <linux/unistd.h>
@@ -162,12 +164,40 @@ static void __zero_source_counters(struct hist_entry *he)
        symbol__annotate_zero_histograms(sym);
 }
 
+static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
+{
+       struct utsname uts;
+       int err = uname(&uts);
+
+       ui__warning("Out of bounds address found:\n\n"
+                   "Addr:   %" PRIx64 "\n"
+                   "DSO:    %s %c\n"
+                   "Map:    %" PRIx64 "-%" PRIx64 "\n"
+                   "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n"
+                   "Arch:   %s\n"
+                   "Kernel: %s\n"
+                   "Tools:  %s\n\n"
+                   "Not all samples will be on the annotation output.\n\n"
+                   "Please report to linux-kernel@vger.kernel.org\n",
+                   ip, map->dso->long_name, dso__symtab_origin(map->dso),
+                   map->start, map->end, sym->start, sym->end,
+                   sym->binding == STB_GLOBAL ? 'g' :
+                   sym->binding == STB_LOCAL  ? 'l' : 'w', sym->name,
+                   err ? "[unknown]" : uts.machine,
+                   err ? "[unknown]" : uts.release, perf_version_string);
+       if (use_browser <= 0)
+               sleep(5);
+       
+       map->erange_warned = true;
+}
+
 static void perf_top__record_precise_ip(struct perf_top *top,
                                        struct hist_entry *he,
                                        int counter, u64 ip)
 {
        struct annotation *notes;
        struct symbol *sym;
+       int err;
 
        if (he == NULL || he->ms.sym == NULL ||
            ((top->sym_filter_entry == NULL ||
@@ -189,9 +219,12 @@ static void perf_top__record_precise_ip(struct perf_top *top,
        }
 
        ip = he->ms.map->map_ip(he->ms.map, ip);
-       symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
+       err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
 
        pthread_mutex_unlock(&notes->lock);
+
+       if (err == -ERANGE && !he->ms.map->erange_warned)
+               ui__warn_map_erange(he->ms.map, sym, ip);
 }
 
 static void perf_top__show_details(struct perf_top *top)
@@ -615,6 +648,7 @@ process_hotkey:
 
 /* Tag samples to be skipped. */
 static const char *skip_symbols[] = {
+       "intel_idle",
        "default_idle",
        "native_safe_halt",
        "cpu_idle",
index 199f69ec656f7a77c5c490e2f1195c9e09226e98..08c6d138a655c09398f05c6b1c4affdf1cb0ec56 100644 (file)
@@ -64,8 +64,8 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 
        pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
 
-       if (addr > sym->end)
-               return 0;
+       if (addr < sym->start || addr > sym->end)
+               return -ERANGE;
 
        offset = addr - sym->start;
        h = annotation__histogram(notes, evidx);
@@ -561,16 +561,12 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
 {
        struct annotation *notes = symbol__annotation(sym);
        struct sym_hist *h = annotation__histogram(notes, evidx);
-       struct objdump_line *pos;
-       int len = sym->end - sym->start;
+       int len = sym->end - sym->start, offset;
 
        h->sum = 0;
-
-       list_for_each_entry(pos, &notes->src->source, node) {
-               if (pos->offset != -1 && pos->offset < len) {
-                       h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
-                       h->sum += h->addr[pos->offset];
-               }
+       for (offset = 0; offset < len; ++offset) {
+               h->addr[offset] = h->addr[offset] * 7 / 8;
+               h->sum += h->addr[offset];
        }
 }
 
index 2ec4b60aff6c1efa5929c53e3c572b1d6504cfbd..9f6d630d53161e6f314e2efd51a90c3cb329521e 100644 (file)
@@ -256,6 +256,18 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
                if (!cmp) {
                        he->period += period;
                        ++he->nr_events;
+
+                       /* If the map of an existing hist_entry has
+                        * become out-of-date due to an exec() or
+                        * similar, update it.  Otherwise we will
+                        * mis-adjust symbol addresses when computing
+                        * the history counter to increment.
+                        */
+                       if (he->ms.map != entry->ms.map) {
+                               he->ms.map = entry->ms.map;
+                               if (he->ms.map)
+                                       he->ms.map->referenced = true;
+                       }
                        goto out;
                }
 
index dea6d1c1a95471018cdde36d0a4c23e20c8f64a1..35ae56864e4f59625369941886b196438f107c99 100644 (file)
@@ -38,6 +38,7 @@ void map__init(struct map *self, enum map_type type,
        RB_CLEAR_NODE(&self->rb_node);
        self->groups   = NULL;
        self->referenced = false;
+       self->erange_warned = false;
 }
 
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
index b100c20b7f94f653448eaafcfb70e61e314f9e22..81371bad4ef0e43e1121b5b8c4367fe4d6b212d8 100644 (file)
@@ -33,6 +33,7 @@ struct map {
        u64                     end;
        u8 /* enum map_type */  type;
        bool                    referenced;
+       bool                    erange_warned;
        u32                     priv;
        u64                     pgoff;
 
index 9412e3b05f6888c9504c7ab6b3dd0effe73de627..00923cda4d9c301c1741b7fc209226ffe54740b1 100644 (file)
@@ -826,8 +826,16 @@ static struct machine *
 {
        const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
-       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
-               return perf_session__find_machine(session, event->ip.pid);
+       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);
 }
index d7a1c4afe28b9089ab09bbf5b7abce623e46a544..2f83e5dc996706a005dcdc9c1cac3cb88d38b94d 100644 (file)
@@ -125,6 +125,9 @@ static int callchain__count_rows(struct rb_root *chain)
 
 static bool map_symbol__toggle_fold(struct map_symbol *self)
 {
+       if (!self)
+               return false;
+
        if (!self->has_children)
                return false;