]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - tools/perf/util/probe-event.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / tools / perf / util / probe-event.c
index 61191c6cbe7a8d04af83e1af5426029a73bc7b99..6e29d9c9dcccb50f63adac097bc512b56fb3e28c 100644 (file)
@@ -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:
@@ -149,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);
@@ -171,7 +172,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
        sym = __find_kernel_function_by_name(tp->symbol, &map);
        if (sym) {
                addr = map->unmap_ip(map, sym->start + tp->offset);
-               pr_debug("try to find %s+%ld@%llx\n", tp->symbol,
+               pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
                         tp->offset, addr);
                ret = find_perf_probe_point((unsigned long)addr, pp);
        }
@@ -226,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;
                }
        }
@@ -295,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;
+       const char *color = show_num ? "" : PERF_COLOR_BLUE;
+       const char *prefix = NULL;
 
-       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);
-       }
-
-       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.
@@ -379,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) {
@@ -388,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;
@@ -466,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;
        }
 
@@ -526,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 */
@@ -699,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;
        }
 
@@ -1005,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;
 }
@@ -1033,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;
        }
@@ -1055,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);
@@ -1796,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;
        }