diff options
| -rw-r--r-- | tools/perf/builtin-top.c | 36 | ||||
| -rw-r--r-- | tools/perf/util/annotate.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/hist.c | 12 | ||||
| -rw-r--r-- | tools/perf/util/map.c | 1 | ||||
| -rw-r--r-- | tools/perf/util/map.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 12 | ||||
| -rw-r--r-- | tools/perf/util/ui/browsers/hists.c | 3 |
7 files changed, 68 insertions, 13 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index e3c63aef8efc..8ef59f8262bb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include "util/debug.h" | 42 | #include "util/debug.h" |
| 43 | 43 | ||
| 44 | #include <assert.h> | 44 | #include <assert.h> |
| 45 | #include <elf.h> | ||
| 45 | #include <fcntl.h> | 46 | #include <fcntl.h> |
| 46 | 47 | ||
| 47 | #include <stdio.h> | 48 | #include <stdio.h> |
| @@ -59,6 +60,7 @@ | |||
| 59 | #include <sys/prctl.h> | 60 | #include <sys/prctl.h> |
| 60 | #include <sys/wait.h> | 61 | #include <sys/wait.h> |
| 61 | #include <sys/uio.h> | 62 | #include <sys/uio.h> |
| 63 | #include <sys/utsname.h> | ||
| 62 | #include <sys/mman.h> | 64 | #include <sys/mman.h> |
| 63 | 65 | ||
| 64 | #include <linux/unistd.h> | 66 | #include <linux/unistd.h> |
| @@ -162,12 +164,40 @@ static void __zero_source_counters(struct hist_entry *he) | |||
| 162 | symbol__annotate_zero_histograms(sym); | 164 | symbol__annotate_zero_histograms(sym); |
| 163 | } | 165 | } |
| 164 | 166 | ||
| 167 | static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) | ||
| 168 | { | ||
| 169 | struct utsname uts; | ||
| 170 | int err = uname(&uts); | ||
| 171 | |||
| 172 | ui__warning("Out of bounds address found:\n\n" | ||
| 173 | "Addr: %" PRIx64 "\n" | ||
| 174 | "DSO: %s %c\n" | ||
| 175 | "Map: %" PRIx64 "-%" PRIx64 "\n" | ||
| 176 | "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n" | ||
| 177 | "Arch: %s\n" | ||
| 178 | "Kernel: %s\n" | ||
| 179 | "Tools: %s\n\n" | ||
| 180 | "Not all samples will be on the annotation output.\n\n" | ||
| 181 | "Please report to linux-kernel@vger.kernel.org\n", | ||
| 182 | ip, map->dso->long_name, dso__symtab_origin(map->dso), | ||
| 183 | map->start, map->end, sym->start, sym->end, | ||
| 184 | sym->binding == STB_GLOBAL ? 'g' : | ||
| 185 | sym->binding == STB_LOCAL ? 'l' : 'w', sym->name, | ||
| 186 | err ? "[unknown]" : uts.machine, | ||
| 187 | err ? "[unknown]" : uts.release, perf_version_string); | ||
| 188 | if (use_browser <= 0) | ||
| 189 | sleep(5); | ||
| 190 | |||
| 191 | map->erange_warned = true; | ||
| 192 | } | ||
| 193 | |||
| 165 | static void perf_top__record_precise_ip(struct perf_top *top, | 194 | static void perf_top__record_precise_ip(struct perf_top *top, |
| 166 | struct hist_entry *he, | 195 | struct hist_entry *he, |
| 167 | int counter, u64 ip) | 196 | int counter, u64 ip) |
| 168 | { | 197 | { |
| 169 | struct annotation *notes; | 198 | struct annotation *notes; |
| 170 | struct symbol *sym; | 199 | struct symbol *sym; |
| 200 | int err; | ||
| 171 | 201 | ||
| 172 | if (he == NULL || he->ms.sym == NULL || | 202 | if (he == NULL || he->ms.sym == NULL || |
| 173 | ((top->sym_filter_entry == NULL || | 203 | ((top->sym_filter_entry == NULL || |
| @@ -189,9 +219,12 @@ static void perf_top__record_precise_ip(struct perf_top *top, | |||
| 189 | } | 219 | } |
| 190 | 220 | ||
| 191 | ip = he->ms.map->map_ip(he->ms.map, ip); | 221 | ip = he->ms.map->map_ip(he->ms.map, ip); |
| 192 | symbol__inc_addr_samples(sym, he->ms.map, counter, ip); | 222 | err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip); |
| 193 | 223 | ||
| 194 | pthread_mutex_unlock(¬es->lock); | 224 | pthread_mutex_unlock(¬es->lock); |
| 225 | |||
| 226 | if (err == -ERANGE && !he->ms.map->erange_warned) | ||
| 227 | ui__warn_map_erange(he->ms.map, sym, ip); | ||
| 195 | } | 228 | } |
| 196 | 229 | ||
| 197 | static void perf_top__show_details(struct perf_top *top) | 230 | static void perf_top__show_details(struct perf_top *top) |
| @@ -615,6 +648,7 @@ process_hotkey: | |||
| 615 | 648 | ||
| 616 | /* Tag samples to be skipped. */ | 649 | /* Tag samples to be skipped. */ |
| 617 | static const char *skip_symbols[] = { | 650 | static const char *skip_symbols[] = { |
| 651 | "intel_idle", | ||
| 618 | "default_idle", | 652 | "default_idle", |
| 619 | "native_safe_halt", | 653 | "native_safe_halt", |
| 620 | "cpu_idle", | 654 | "cpu_idle", |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 199f69ec656f..08c6d138a655 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
| @@ -64,8 +64,8 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
| 64 | 64 | ||
| 65 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); | 65 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); |
| 66 | 66 | ||
| 67 | if (addr > sym->end) | 67 | if (addr < sym->start || addr > sym->end) |
| 68 | return 0; | 68 | return -ERANGE; |
| 69 | 69 | ||
| 70 | offset = addr - sym->start; | 70 | offset = addr - sym->start; |
| 71 | h = annotation__histogram(notes, evidx); | 71 | h = annotation__histogram(notes, evidx); |
| @@ -561,16 +561,12 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) | |||
| 561 | { | 561 | { |
| 562 | struct annotation *notes = symbol__annotation(sym); | 562 | struct annotation *notes = symbol__annotation(sym); |
| 563 | struct sym_hist *h = annotation__histogram(notes, evidx); | 563 | struct sym_hist *h = annotation__histogram(notes, evidx); |
| 564 | struct objdump_line *pos; | 564 | int len = sym->end - sym->start, offset; |
| 565 | int len = sym->end - sym->start; | ||
| 566 | 565 | ||
| 567 | h->sum = 0; | 566 | h->sum = 0; |
| 568 | 567 | for (offset = 0; offset < len; ++offset) { | |
| 569 | list_for_each_entry(pos, ¬es->src->source, node) { | 568 | h->addr[offset] = h->addr[offset] * 7 / 8; |
| 570 | if (pos->offset != -1 && pos->offset < len) { | 569 | h->sum += h->addr[offset]; |
| 571 | h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; | ||
| 572 | h->sum += h->addr[pos->offset]; | ||
| 573 | } | ||
| 574 | } | 570 | } |
| 575 | } | 571 | } |
| 576 | 572 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 2ec4b60aff6c..9f6d630d5316 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -256,6 +256,18 @@ static struct hist_entry *add_hist_entry(struct hists *hists, | |||
| 256 | if (!cmp) { | 256 | if (!cmp) { |
| 257 | he->period += period; | 257 | he->period += period; |
| 258 | ++he->nr_events; | 258 | ++he->nr_events; |
| 259 | |||
| 260 | /* If the map of an existing hist_entry has | ||
| 261 | * become out-of-date due to an exec() or | ||
| 262 | * similar, update it. Otherwise we will | ||
| 263 | * mis-adjust symbol addresses when computing | ||
| 264 | * the history counter to increment. | ||
| 265 | */ | ||
| 266 | if (he->ms.map != entry->ms.map) { | ||
| 267 | he->ms.map = entry->ms.map; | ||
| 268 | if (he->ms.map) | ||
| 269 | he->ms.map->referenced = true; | ||
| 270 | } | ||
| 259 | goto out; | 271 | goto out; |
| 260 | } | 272 | } |
| 261 | 273 | ||
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index dea6d1c1a954..35ae56864e4f 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -38,6 +38,7 @@ void map__init(struct map *self, enum map_type type, | |||
| 38 | RB_CLEAR_NODE(&self->rb_node); | 38 | RB_CLEAR_NODE(&self->rb_node); |
| 39 | self->groups = NULL; | 39 | self->groups = NULL; |
| 40 | self->referenced = false; | 40 | self->referenced = false; |
| 41 | self->erange_warned = false; | ||
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 44 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index b100c20b7f94..81371bad4ef0 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -33,6 +33,7 @@ struct map { | |||
| 33 | u64 end; | 33 | u64 end; |
| 34 | u8 /* enum map_type */ type; | 34 | u8 /* enum map_type */ type; |
| 35 | bool referenced; | 35 | bool referenced; |
| 36 | bool erange_warned; | ||
| 36 | u32 priv; | 37 | u32 priv; |
| 37 | u64 pgoff; | 38 | u64 pgoff; |
| 38 | 39 | ||
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 9412e3b05f68..00923cda4d9c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -826,8 +826,16 @@ static struct machine * | |||
| 826 | { | 826 | { |
| 827 | const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 827 | const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
| 828 | 828 | ||
| 829 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) | 829 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { |
| 830 | return perf_session__find_machine(session, event->ip.pid); | 830 | u32 pid; |
| 831 | |||
| 832 | if (event->header.type == PERF_RECORD_MMAP) | ||
| 833 | pid = event->mmap.pid; | ||
| 834 | else | ||
| 835 | pid = event->ip.pid; | ||
| 836 | |||
| 837 | return perf_session__find_machine(session, pid); | ||
| 838 | } | ||
| 831 | 839 | ||
| 832 | return perf_session__find_host_machine(session); | 840 | return perf_session__find_host_machine(session); |
| 833 | } | 841 | } |
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index d7a1c4afe28b..2f83e5dc9967 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c | |||
| @@ -125,6 +125,9 @@ static int callchain__count_rows(struct rb_root *chain) | |||
| 125 | 125 | ||
| 126 | static bool map_symbol__toggle_fold(struct map_symbol *self) | 126 | static bool map_symbol__toggle_fold(struct map_symbol *self) |
| 127 | { | 127 | { |
| 128 | if (!self) | ||
| 129 | return false; | ||
| 130 | |||
| 128 | if (!self->has_children) | 131 | if (!self->has_children) |
| 129 | return false; | 132 | return false; |
| 130 | 133 | ||
