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

Merge tag 'perf-tools-fixes-for-v5.15-2021-09-18' of...

Merge tag 'perf-tools-fixes-for-v5.15-2021-09-18' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Fix ip display in 'perf script' when output type != attr->type.

 - Ignore deprecation warning when using libbpf'sg btf__get_from_id(),
   fixing the build with libbpf v0.6+.

 - Make use of FD() robust in libperf, fixing a segfault with 'perf stat
   --iostat list'.

 - Initialize addr_location:srcline pointer to NULL when resolving
   callchain addresses.

 - Fix fused instruction logic for assembly functions in 'perf
   annotate'.

* tag 'perf-tools-fixes-for-v5.15-2021-09-18' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
  perf bpf: Ignore deprecation warning when using libbpf's btf__get_from_id()
  libperf evsel: Make use of FD robust.
  perf machine: Initialize srcline string member in add_location struct
  perf script: Fix ip display when type != attr->type
  perf annotate: Fix fused instr logic for assembly functions
parents bc1abb9e 219d720e
Loading
Loading
Loading
Loading
+41 −23
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ void perf_evsel__delete(struct perf_evsel *evsel)
	free(evsel);
}

#define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y))
#define FD(e, x, y) ((int *) xyarray__entry(e->fd, x, y))
#define MMAP(e, x, y) (e->mmap ? ((struct perf_mmap *) xyarray__entry(e->mmap, x, y)) : NULL)

int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -54,7 +54,10 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
		int cpu, thread;
		for (cpu = 0; cpu < ncpus; cpu++) {
			for (thread = 0; thread < nthreads; thread++) {
				FD(evsel, cpu, thread) = -1;
				int *fd = FD(evsel, cpu, thread);

				if (fd)
					*fd = -1;
			}
		}
	}
@@ -80,7 +83,7 @@ sys_perf_event_open(struct perf_event_attr *attr,
static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread, int *group_fd)
{
	struct perf_evsel *leader = evsel->leader;
	int fd;
	int *fd;

	if (evsel == leader) {
		*group_fd = -1;
@@ -95,10 +98,10 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread, int *grou
		return -ENOTCONN;

	fd = FD(leader, cpu, thread);
	if (fd == -1)
	if (fd == NULL || *fd == -1)
		return -EBADF;

	*group_fd = fd;
	*group_fd = *fd;

	return 0;
}
@@ -138,7 +141,11 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,

	for (cpu = 0; cpu < cpus->nr; cpu++) {
		for (thread = 0; thread < threads->nr; thread++) {
			int fd, group_fd;
			int fd, group_fd, *evsel_fd;

			evsel_fd = FD(evsel, cpu, thread);
			if (evsel_fd == NULL)
				return -EINVAL;

			err = get_group_fd(evsel, cpu, thread, &group_fd);
			if (err < 0)
@@ -151,7 +158,7 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
			if (fd < 0)
				return -errno;

			FD(evsel, cpu, thread) = fd;
			*evsel_fd = fd;
		}
	}

@@ -163,9 +170,12 @@ static void perf_evsel__close_fd_cpu(struct perf_evsel *evsel, int cpu)
	int thread;

	for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
		if (FD(evsel, cpu, thread) >= 0)
			close(FD(evsel, cpu, thread));
		FD(evsel, cpu, thread) = -1;
		int *fd = FD(evsel, cpu, thread);

		if (fd && *fd >= 0) {
			close(*fd);
			*fd = -1;
		}
	}
}

@@ -209,13 +219,12 @@ void perf_evsel__munmap(struct perf_evsel *evsel)

	for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
		for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
			int fd = FD(evsel, cpu, thread);
			struct perf_mmap *map = MMAP(evsel, cpu, thread);
			int *fd = FD(evsel, cpu, thread);

			if (fd < 0)
			if (fd == NULL || *fd < 0)
				continue;

			perf_mmap__munmap(map);
			perf_mmap__munmap(MMAP(evsel, cpu, thread));
		}
	}

@@ -239,15 +248,16 @@ int perf_evsel__mmap(struct perf_evsel *evsel, int pages)

	for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
		for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
			int fd = FD(evsel, cpu, thread);
			struct perf_mmap *map = MMAP(evsel, cpu, thread);
			int *fd = FD(evsel, cpu, thread);
			struct perf_mmap *map;

			if (fd < 0)
			if (fd == NULL || *fd < 0)
				continue;

			map = MMAP(evsel, cpu, thread);
			perf_mmap__init(map, NULL, false, NULL);

			ret = perf_mmap__mmap(map, &mp, fd, cpu);
			ret = perf_mmap__mmap(map, &mp, *fd, cpu);
			if (ret) {
				perf_evsel__munmap(evsel);
				return ret;
@@ -260,7 +270,9 @@ int perf_evsel__mmap(struct perf_evsel *evsel, int pages)

void *perf_evsel__mmap_base(struct perf_evsel *evsel, int cpu, int thread)
{
	if (FD(evsel, cpu, thread) < 0 || MMAP(evsel, cpu, thread) == NULL)
	int *fd = FD(evsel, cpu, thread);

	if (fd == NULL || *fd < 0 || MMAP(evsel, cpu, thread) == NULL)
		return NULL;

	return MMAP(evsel, cpu, thread)->base;
@@ -295,17 +307,18 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
		     struct perf_counts_values *count)
{
	size_t size = perf_evsel__read_size(evsel);
	int *fd = FD(evsel, cpu, thread);

	memset(count, 0, sizeof(*count));

	if (FD(evsel, cpu, thread) < 0)
	if (fd == NULL || *fd < 0)
		return -EINVAL;

	if (MMAP(evsel, cpu, thread) &&
	    !perf_mmap__read_self(MMAP(evsel, cpu, thread), count))
		return 0;

	if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
	if (readn(*fd, count->values, size) <= 0)
		return -errno;

	return 0;
@@ -318,8 +331,13 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
	int thread;

	for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
		int fd = FD(evsel, cpu, thread),
		    err = ioctl(fd, ioc, arg);
		int err;
		int *fd = FD(evsel, cpu, thread);

		if (fd == NULL || *fd < 0)
			return -1;

		err = ioctl(*fd, ioc, arg);

		if (err)
			return err;
+13 −11
Original line number Diff line number Diff line
@@ -368,16 +368,6 @@ static inline int output_type(unsigned int type)
	return OUTPUT_TYPE_OTHER;
}

static inline unsigned int attr_type(unsigned int type)
{
	switch (type) {
	case OUTPUT_TYPE_SYNTH:
		return PERF_TYPE_SYNTH;
	default:
		return type;
	}
}

static bool output_set_by_user(void)
{
	int j;
@@ -556,6 +546,18 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
		output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
}

static struct evsel *find_first_output_type(struct evlist *evlist,
					    unsigned int type)
{
	struct evsel *evsel;

	evlist__for_each_entry(evlist, evsel) {
		if (output_type(evsel->core.attr.type) == (int)type)
			return evsel;
	}
	return NULL;
}

/*
 * verify all user requested events exist and the samples
 * have the expected data
@@ -567,7 +569,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
	struct evsel *evsel;

	for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
		evsel = perf_session__find_first_evtype(session, attr_type(j));
		evsel = find_first_output_type(session->evlist, j);

		/*
		 * even if fields is set to 0 (ie., show nothing) event must
+24 −9
Original line number Diff line number Diff line
@@ -757,25 +757,40 @@ void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
}

void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
			    unsigned int row, bool arrow_down)
			    unsigned int row, int diff, bool arrow_down)
{
	unsigned int end_row;
	int end_row;

	if (row >= browser->top_idx)
		end_row = row - browser->top_idx;
	else
	if (diff <= 0)
		return;

	SLsmg_set_char_set(1);

	if (arrow_down) {
		if (row + diff <= browser->top_idx)
			return;

		end_row = row + diff - browser->top_idx;
		ui_browser__gotorc(browser, end_row, column - 1);
		SLsmg_write_char(SLSMG_LTEE_CHAR);

		while (--end_row >= 0 && end_row > (int)(row - browser->top_idx)) {
			ui_browser__gotorc(browser, end_row, column - 1);
			SLsmg_draw_vline(1);
		}

		end_row = (int)(row - browser->top_idx);
		if (end_row >= 0) {
			ui_browser__gotorc(browser, end_row, column - 1);
			SLsmg_write_char(SLSMG_ULCORN_CHAR);
			ui_browser__gotorc(browser, end_row, column);
			SLsmg_draw_hline(2);
		ui_browser__gotorc(browser, end_row + 1, column - 1);
		SLsmg_write_char(SLSMG_LTEE_CHAR);
		}
	} else {
		if (row < browser->top_idx)
			return;

		end_row = row - browser->top_idx;
		ui_browser__gotorc(browser, end_row, column - 1);
		SLsmg_write_char(SLSMG_LTEE_CHAR);
		ui_browser__gotorc(browser, end_row, column);
+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ void ui_browser__write_graph(struct ui_browser *browser, int graph);
void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
			      u64 start, u64 end);
void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column,
			    unsigned int row, bool arrow_down);
			    unsigned int row, int diff, bool arrow_down);
void __ui_browser__show_title(struct ui_browser *browser, const char *title);
void ui_browser__show_title(struct ui_browser *browser, const char *title);
int ui_browser__show(struct ui_browser *browser, const char *title,
+17 −7
Original line number Diff line number Diff line
@@ -125,13 +125,20 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
		ab->selection = al;
}

static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
static int is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
{
	struct disasm_line *pos = list_prev_entry(cursor, al.node);
	const char *name;
	int diff = 1;

	while (pos && pos->al.offset == -1) {
		pos = list_prev_entry(pos, al.node);
		if (!ab->opts->hide_src_code)
			diff++;
	}

	if (!pos)
		return false;
		return 0;

	if (ins__is_lock(&pos->ins))
		name = pos->ops.locked.ins.name;
@@ -139,9 +146,11 @@ static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
		name = pos->ins.name;

	if (!name || !cursor->ins.name)
		return false;
		return 0;

	return ins__is_fused(ab->arch, name, cursor->ins.name);
	if (ins__is_fused(ab->arch, name, cursor->ins.name))
		return diff;
	return 0;
}

static void annotate_browser__draw_current_jump(struct ui_browser *browser)
@@ -155,6 +164,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
	struct annotation *notes = symbol__annotation(sym);
	u8 pcnt_width = annotation__pcnt_width(notes);
	int width;
	int diff = 0;

	/* PLT symbols contain external offsets */
	if (strstr(sym->name, "@plt"))
@@ -205,11 +215,11 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
				 pcnt_width + 2 + notes->widths.addr + width,
				 from, to);

	if (is_fused(ab, cursor)) {
	diff = is_fused(ab, cursor);
	if (diff > 0) {
		ui_browser__mark_fused(browser,
				       pcnt_width + 3 + notes->widths.addr + width,
				       from - 1,
				       to > from);
				       from - diff, diff, to > from);
	}
}

Loading