Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bfecc60d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -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 @@ static void *display_thread(void *arg)

/* Tag samples to be skipped. */
static const char *skip_symbols[] = {
	"intel_idle",
	"default_idle",
	"native_safe_halt",
	"cpu_idle",
+6 −10
Original line number Diff line number Diff line
@@ -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];
	}
}

+12 −0
Original line number Diff line number Diff line
@@ -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;
		}

+1 −0
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct map {
	u64			end;
	u8 /* enum map_type */	type;
	bool			referenced;
	bool			erange_warned;
	u32			priv;
	u64			pgoff;

Loading