diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r-- | tools/perf/util/probe-event.c | 249 |
1 files changed, 151 insertions, 98 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 3b6a5297bf16..128aaab0aeda 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -95,7 +95,7 @@ static int init_vmlinux(void) goto out; if (machine__create_kernel_maps(&machine) < 0) { - pr_debug("machine__create_kernel_maps "); + pr_debug("machine__create_kernel_maps() failed.\n"); goto out; } out: @@ -114,6 +114,8 @@ static struct symbol *__find_kernel_function_by_name(const char *name, const char *kernel_get_module_path(const char *module) { struct dso *dso; + struct map *map; + const char *vmlinux_name; if (module) { list_for_each_entry(dso, &machine.kernel_dsos, node) { @@ -123,10 +125,17 @@ const char *kernel_get_module_path(const char *module) } pr_debug("Failed to find module %s.\n", module); return NULL; + } + + map = machine.vmlinux_maps[MAP__FUNCTION]; + dso = map->dso; + + vmlinux_name = symbol_conf.vmlinux_name; + if (vmlinux_name) { + if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0) + return NULL; } else { - dso = machine.vmlinux_maps[MAP__FUNCTION]->dso; - if (dso__load_vmlinux_path(dso, - machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { + if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { pr_debug("Failed to load kernel map.\n"); return NULL; } @@ -140,7 +149,8 @@ static int open_vmlinux(const char *module) { const char *path = kernel_get_module_path(module); if (!path) { - pr_err("Failed to find path of %s module", module ?: "kernel"); + pr_err("Failed to find path of %s module.\n", + module ?: "kernel"); return -ENOENT; } pr_debug("Try to open %s\n", path); @@ -217,7 +227,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, pr_warning("Warning: No dwarf info found in the vmlinux - " "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); if (!need_dwarf) { - pr_debug("Trying to use symbols.\nn"); + pr_debug("Trying to use symbols.\n"); return 0; } } @@ -286,42 +296,49 @@ static int get_real_path(const char *raw_path, const char *comp_dir, #define LINEBUF_SIZE 256 #define NR_ADDITIONAL_LINES 2 -static int show_one_line(FILE *fp, int l, bool skip, bool show_num) +static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) { char buf[LINEBUF_SIZE]; - const char *color = PERF_COLOR_BLUE; - - if (fgets(buf, LINEBUF_SIZE, fp) == NULL) - goto error; - if (!skip) { - if (show_num) - fprintf(stdout, "%7d %s", l, buf); - else - color_fprintf(stdout, color, " %s", buf); - } + const char *color = show_num ? "" : PERF_COLOR_BLUE; + const char *prefix = NULL; - while (strlen(buf) == LINEBUF_SIZE - 1 && - buf[LINEBUF_SIZE - 2] != '\n') { + do { if (fgets(buf, LINEBUF_SIZE, fp) == NULL) goto error; - if (!skip) { - if (show_num) - fprintf(stdout, "%s", buf); - else - color_fprintf(stdout, color, "%s", buf); + if (skip) + continue; + if (!prefix) { + prefix = show_num ? "%7d " : " "; + color_fprintf(stdout, color, prefix, l); } - } + color_fprintf(stdout, color, "%s", buf); - return 0; + } while (strchr(buf, '\n') == NULL); + + return 1; error: - if (feof(fp)) - pr_warning("Source file is shorter than expected.\n"); - else + if (ferror(fp)) { pr_warning("File read error: %s\n", strerror(errno)); + return -1; + } + return 0; +} - return -1; +static int _show_one_line(FILE *fp, int l, bool skip, bool show_num) +{ + int rv = __show_one_line(fp, l, skip, show_num); + if (rv == 0) { + pr_warning("Source file is shorter than expected.\n"); + rv = -1; + } + return rv; } +#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true) +#define show_one_line(f,l) _show_one_line(f,l,false,false) +#define skip_one_line(f,l) _show_one_line(f,l,true,false) +#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false) + /* * Show line-range always requires debuginfo to find source file and * line number. @@ -370,7 +387,7 @@ int show_line_range(struct line_range *lr, const char *module) fprintf(stdout, "<%s:%d>\n", lr->function, lr->start - lr->offset); else - fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); + fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); fp = fopen(lr->path, "r"); if (fp == NULL) { @@ -379,26 +396,30 @@ int show_line_range(struct line_range *lr, const char *module) return -errno; } /* Skip to starting line number */ - while (l < lr->start && ret >= 0) - ret = show_one_line(fp, l++, true, false); - if (ret < 0) - goto end; + while (l < lr->start) { + ret = skip_one_line(fp, l++); + if (ret < 0) + goto end; + } list_for_each_entry(ln, &lr->line_list, list) { - while (ln->line > l && ret >= 0) - ret = show_one_line(fp, (l++) - lr->offset, - false, false); - if (ret >= 0) - ret = show_one_line(fp, (l++) - lr->offset, - false, true); + for (; ln->line > l; l++) { + ret = show_one_line(fp, l - lr->offset); + if (ret < 0) + goto end; + } + ret = show_one_line_with_num(fp, l++ - lr->offset); if (ret < 0) goto end; } if (lr->end == INT_MAX) lr->end = l + NR_ADDITIONAL_LINES; - while (l <= lr->end && !feof(fp) && ret >= 0) - ret = show_one_line(fp, (l++) - lr->offset, false, false); + while (l <= lr->end) { + ret = show_one_line_or_eof(fp, l++ - lr->offset); + if (ret <= 0) + break; + } end: fclose(fp); return ret; @@ -457,7 +478,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, fd = open_vmlinux(module); if (fd < 0) { - pr_warning("Failed to open debuginfo file.\n"); + pr_warning("Failed to open debug information file.\n"); return fd; } @@ -517,56 +538,87 @@ int show_available_vars(struct perf_probe_event *pevs __unused, } #endif +static int parse_line_num(char **ptr, int *val, const char *what) +{ + const char *start = *ptr; + + errno = 0; + *val = strtol(*ptr, ptr, 0); + if (errno || *ptr == start) { + semantic_error("'%s' is not a valid number.\n", what); + return -EINVAL; + } + return 0; +} + +/* + * Stuff 'lr' according to the line range described by 'arg'. + * The line range syntax is described by: + * + * SRC[:SLN[+NUM|-ELN]] + * FNC[:SLN[+NUM|-ELN]] + */ int parse_line_range_desc(const char *arg, struct line_range *lr) { - const char *ptr; - char *tmp; - /* - * <Syntax> - * SRC:SLN[+NUM|-ELN] - * FUNC[:SLN[+NUM|-ELN]] - */ - ptr = strchr(arg, ':'); - if (ptr) { - lr->start = (int)strtoul(ptr + 1, &tmp, 0); - if (*tmp == '+') { - lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); - lr->end--; /* - * Adjust the number of lines here. - * If the number of lines == 1, the - * the end of line should be equal to - * the start of line. - */ - } else if (*tmp == '-') - lr->end = (int)strtoul(tmp + 1, &tmp, 0); - else - lr->end = INT_MAX; + char *range, *name = strdup(arg); + int err; + + if (!name) + return -ENOMEM; + + lr->start = 0; + lr->end = INT_MAX; + + range = strchr(name, ':'); + if (range) { + *range++ = '\0'; + + err = parse_line_num(&range, &lr->start, "start line"); + if (err) + goto err; + + if (*range == '+' || *range == '-') { + const char c = *range++; + + err = parse_line_num(&range, &lr->end, "end line"); + if (err) + goto err; + + if (c == '+') { + lr->end += lr->start; + /* + * Adjust the number of lines here. + * If the number of lines == 1, the + * the end of line should be equal to + * the start of line. + */ + lr->end--; + } + } + pr_debug("Line range is %d to %d\n", lr->start, lr->end); + + err = -EINVAL; if (lr->start > lr->end) { semantic_error("Start line must be smaller" " than end line.\n"); - return -EINVAL; + goto err; } - if (*tmp != '\0') { - semantic_error("Tailing with invalid character '%d'.\n", - *tmp); - return -EINVAL; + if (*range != '\0') { + semantic_error("Tailing with invalid str '%s'.\n", range); + goto err; } - tmp = strndup(arg, (ptr - arg)); - } else { - tmp = strdup(arg); - lr->end = INT_MAX; } - if (tmp == NULL) - return -ENOMEM; - - if (strchr(tmp, '.')) - lr->file = tmp; + if (strchr(name, '.')) + lr->file = name; else - lr->function = tmp; + lr->function = name; return 0; +err: + free(name); + return err; } /* Check the name is good for event/group */ @@ -690,39 +742,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) /* Exclusion check */ if (pp->lazy_line && pp->line) { - semantic_error("Lazy pattern can't be used with line number."); + semantic_error("Lazy pattern can't be used with" + " line number.\n"); return -EINVAL; } if (pp->lazy_line && pp->offset) { - semantic_error("Lazy pattern can't be used with offset."); + semantic_error("Lazy pattern can't be used with offset.\n"); return -EINVAL; } if (pp->line && pp->offset) { - semantic_error("Offset can't be used with line number."); + semantic_error("Offset can't be used with line number.\n"); return -EINVAL; } if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { semantic_error("File always requires line number or " - "lazy pattern."); + "lazy pattern.\n"); return -EINVAL; } if (pp->offset && !pp->function) { - semantic_error("Offset requires an entry function."); + semantic_error("Offset requires an entry function.\n"); return -EINVAL; } if (pp->retprobe && !pp->function) { - semantic_error("Return probe requires an entry function."); + semantic_error("Return probe requires an entry function.\n"); return -EINVAL; } if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { semantic_error("Offset/Line/Lazy pattern can't be used with " - "return probe."); + "return probe.\n"); return -EINVAL; } @@ -996,7 +1049,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) return tmp - buf; error: - pr_debug("Failed to synthesize perf probe argument: %s", + pr_debug("Failed to synthesize perf probe argument: %s\n", strerror(-ret)); return ret; } @@ -1024,13 +1077,13 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) goto error; } if (pp->file) { - len = strlen(pp->file) - 31; - if (len < 0) - len = 0; - tmp = strchr(pp->file + len, '/'); - if (!tmp) - tmp = pp->file + len; - ret = e_snprintf(file, 32, "@%s", tmp + 1); + tmp = pp->file; + len = strlen(tmp); + if (len > 30) { + tmp = strchr(pp->file + len - 30, '/'); + tmp = tmp ? tmp + 1 : pp->file + len - 30; + } + ret = e_snprintf(file, 32, "@%s", tmp); if (ret <= 0) goto error; } @@ -1046,7 +1099,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) return buf; error: - pr_debug("Failed to synthesize perf probe point: %s", + pr_debug("Failed to synthesize perf probe point: %s\n", strerror(-ret)); if (buf) free(buf); @@ -1787,7 +1840,7 @@ static int del_trace_probe_event(int fd, const char *group, ret = e_snprintf(buf, 128, "%s:%s", group, event); if (ret < 0) { - pr_err("Failed to copy event."); + pr_err("Failed to copy event.\n"); return ret; } |