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

Commit 7cf0b79e authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo
Browse files

perf probe: Fix error message if get_real_path() failed



Perf probe -L shows incorrect error message (Dwarf error) if it fails to find
source file. This can confuse users.

# ./perf probe -s /nowhere -L vfs_read
Debuginfo analysis failed. (-2)
  Error: Failed to show lines. (-2)

With this patch, it shows correct message.

# ./perf probe -s /nowhere -L vfs_read
Failed to find source file. (-2)
  Error: Failed to show lines. (-2)

LKML-Reference: <4C36EBDB.4020308@hitachi.com>
Cc: Chase Douglas <chase.douglas@canonical.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Acked-by: default avatarChase Douglas <chase.douglas@canonical.com>
Signed-off-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 0dd9ac63
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -195,6 +195,55 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
	return ntevs;
}

/*
 * Find a src file from a DWARF tag path. Prepend optional source path prefix
 * and chop off leading directories that do not exist. Result is passed back as
 * a newly allocated path on success.
 * Return 0 if file was found and readable, -errno otherwise.
 */
static int get_real_path(const char *raw_path, char **new_path)
{
	if (!symbol_conf.source_prefix) {
		if (access(raw_path, R_OK) == 0) {
			*new_path = strdup(raw_path);
			return 0;
		} else
			return -errno;
	}

	*new_path = malloc((strlen(symbol_conf.source_prefix) +
			    strlen(raw_path) + 2));
	if (!*new_path)
		return -ENOMEM;

	for (;;) {
		sprintf(*new_path, "%s/%s", symbol_conf.source_prefix,
			raw_path);

		if (access(*new_path, R_OK) == 0)
			return 0;

		switch (errno) {
		case ENAMETOOLONG:
		case ENOENT:
		case EROFS:
		case EFAULT:
			raw_path = strchr(++raw_path, '/');
			if (!raw_path) {
				free(*new_path);
				*new_path = NULL;
				return -ENOENT;
			}
			continue;

		default:
			free(*new_path);
			*new_path = NULL;
			return -errno;
		}
	}
}

#define LINEBUF_SIZE 256
#define NR_ADDITIONAL_LINES 2

@@ -244,6 +293,7 @@ int show_line_range(struct line_range *lr)
	struct line_node *ln;
	FILE *fp;
	int fd, ret;
	char *tmp;

	/* Search a line range */
	ret = init_vmlinux();
@@ -266,6 +316,15 @@ int show_line_range(struct line_range *lr)
		return ret;
	}

	/* Convert source file path */
	tmp = lr->path;
	ret = get_real_path(tmp, &lr->path);
	free(tmp);	/* Free old path */
	if (ret < 0) {
		pr_warning("Failed to find source file. (%d)\n", ret);
		return ret;
	}

	setup_pager();

	if (lr->function)
+5 −56
Original line number Diff line number Diff line
@@ -58,55 +58,6 @@ static int strtailcmp(const char *s1, const char *s2)
	return 0;
}

/*
 * Find a src file from a DWARF tag path. Prepend optional source path prefix
 * and chop off leading directories that do not exist. Result is passed back as
 * a newly allocated path on success.
 * Return 0 if file was found and readable, -errno otherwise.
 */
static int get_real_path(const char *raw_path, char **new_path)
{
	if (!symbol_conf.source_prefix) {
		if (access(raw_path, R_OK) == 0) {
			*new_path = strdup(raw_path);
			return 0;
		} else
			return -errno;
	}

	*new_path = malloc((strlen(symbol_conf.source_prefix) +
			    strlen(raw_path) + 2));
	if (!*new_path)
		return -ENOMEM;

	for (;;) {
		sprintf(*new_path, "%s/%s", symbol_conf.source_prefix,
			raw_path);

		if (access(*new_path, R_OK) == 0)
			return 0;

		switch (errno) {
		case ENAMETOOLONG:
		case ENOENT:
		case EROFS:
		case EFAULT:
			raw_path = strchr(++raw_path, '/');
			if (!raw_path) {
				free(*new_path);
				*new_path = NULL;
				return -ENOENT;
			}
			continue;

		default:
			free(*new_path);
			*new_path = NULL;
			return -errno;
		}
	}
}

/* Line number list operations */

/* Add a line to line number list */
@@ -1256,13 +1207,11 @@ int find_perf_probe_point(int fd, unsigned long addr,
static int line_range_add_line(const char *src, unsigned int lineno,
			       struct line_range *lr)
{
	int ret;

	/* Copy real path */
	/* Copy source path */
	if (!lr->path) {
		ret = get_real_path(src, &lr->path);
		if (ret != 0)
			return ret;
		lr->path = strdup(src);
		if (lr->path == NULL)
			return -ENOMEM;
	}
	return line_list__add_line(&lr->line_list, lineno);
}
@@ -1460,7 +1409,7 @@ int find_line_range(int fd, struct line_range *lr)
		}
		off = noff;
	}
	pr_debug("path: %lx\n", (unsigned long)lr->path);
	pr_debug("path: %s\n", lr->path);
	dwarf_end(dbg);

	return (ret < 0) ? ret : lf.found;