Commit bfecc60d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf tool fixes from Ingo Molnar.

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf kvm: Finding struct machine fails for PERF_RECORD_MMAP
  perf annotate: Validate addr in symbol__inc_addr_samples
  perf hists browser: Fix NULL deref in hists browsing code
  perf hists: Catch and handle out-of-date hist entry maps.
  perf annotate: Fix hist decay
  perf top: Add intel_idle to the skip list
parents 2084c24a a7ca0803
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "util/debug.h" #include "util/debug.h"
#include <assert.h> #include <assert.h>
#include <elf.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
...@@ -59,6 +60,7 @@ ...@@ -59,6 +60,7 @@
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/utsname.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <linux/unistd.h> #include <linux/unistd.h>
...@@ -162,12 +164,40 @@ static void __zero_source_counters(struct hist_entry *he) ...@@ -162,12 +164,40 @@ static void __zero_source_counters(struct hist_entry *he)
symbol__annotate_zero_histograms(sym); 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, static void perf_top__record_precise_ip(struct perf_top *top,
struct hist_entry *he, struct hist_entry *he,
int counter, u64 ip) int counter, u64 ip)
{ {
struct annotation *notes; struct annotation *notes;
struct symbol *sym; struct symbol *sym;
int err;
if (he == NULL || he->ms.sym == NULL || if (he == NULL || he->ms.sym == NULL ||
((top->sym_filter_entry == NULL || ((top->sym_filter_entry == NULL ||
...@@ -189,9 +219,12 @@ static void perf_top__record_precise_ip(struct perf_top *top, ...@@ -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); 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); 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) static void perf_top__show_details(struct perf_top *top)
...@@ -615,6 +648,7 @@ static void *display_thread(void *arg) ...@@ -615,6 +648,7 @@ static void *display_thread(void *arg)
/* Tag samples to be skipped. */ /* Tag samples to be skipped. */
static const char *skip_symbols[] = { static const char *skip_symbols[] = {
"intel_idle",
"default_idle", "default_idle",
"native_safe_halt", "native_safe_halt",
"cpu_idle", "cpu_idle",
......
...@@ -64,8 +64,8 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, ...@@ -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)); pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
if (addr > sym->end) if (addr < sym->start || addr > sym->end)
return 0; return -ERANGE;
offset = addr - sym->start; offset = addr - sym->start;
h = annotation__histogram(notes, evidx); h = annotation__histogram(notes, evidx);
...@@ -561,16 +561,12 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) ...@@ -561,16 +561,12 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
{ {
struct annotation *notes = symbol__annotation(sym); struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx); struct sym_hist *h = annotation__histogram(notes, evidx);
struct objdump_line *pos; int len = sym->end - sym->start, offset;
int len = sym->end - sym->start;
h->sum = 0; h->sum = 0;
for (offset = 0; offset < len; ++offset) {
list_for_each_entry(pos, &notes->src->source, node) { h->addr[offset] = h->addr[offset] * 7 / 8;
if (pos->offset != -1 && pos->offset < len) { h->sum += h->addr[offset];
h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
h->sum += h->addr[pos->offset];
}
} }
} }
......
...@@ -256,6 +256,18 @@ static struct hist_entry *add_hist_entry(struct hists *hists, ...@@ -256,6 +256,18 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
if (!cmp) { if (!cmp) {
he->period += period; he->period += period;
++he->nr_events; ++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; goto out;
} }
......
...@@ -38,6 +38,7 @@ void map__init(struct map *self, enum map_type type, ...@@ -38,6 +38,7 @@ void map__init(struct map *self, enum map_type type,
RB_CLEAR_NODE(&self->rb_node); RB_CLEAR_NODE(&self->rb_node);
self->groups = NULL; self->groups = NULL;
self->referenced = false; self->referenced = false;
self->erange_warned = false;
} }
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
......
...@@ -33,6 +33,7 @@ struct map { ...@@ -33,6 +33,7 @@ struct map {
u64 end; u64 end;
u8 /* enum map_type */ type; u8 /* enum map_type */ type;
bool referenced; bool referenced;
bool erange_warned;
u32 priv; u32 priv;
u64 pgoff; u64 pgoff;
......
...@@ -826,8 +826,16 @@ static struct machine * ...@@ -826,8 +826,16 @@ static struct machine *
{ {
const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
return perf_session__find_machine(session, event->ip.pid); 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); return perf_session__find_host_machine(session);
} }
......
...@@ -125,6 +125,9 @@ static int callchain__count_rows(struct rb_root *chain) ...@@ -125,6 +125,9 @@ static int callchain__count_rows(struct rb_root *chain)
static bool map_symbol__toggle_fold(struct map_symbol *self) static bool map_symbol__toggle_fold(struct map_symbol *self)
{ {
if (!self)
return false;
if (!self->has_children) if (!self->has_children)
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment