aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorFranck Bui-Huu <fbuihuu@gmail.com>2010-12-20 09:18:05 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-12-21 14:20:13 -0500
commit21dd9ae5a4e9f717f3957ec934dd3158129436b8 (patch)
tree817d9db270a3179f480eeac358d43c0c8655b361 /tools/perf/util
parentfde52dbd7f71934aba4e150f3d1d51e826a08850 (diff)
perf probe: Handle gracefully some stupid and buggy line syntaxes
Currently perf probe doesn't handle those incorrect syntaxes: $ perf probe -L sched.c:++13 $ perf probe -L sched.c:-+13 $ perf probe -L sched.c:10000000000000000000000000000+13 This patches rewrites parse_line_range_desc() to handle them. As a bonus, it reports more useful error messages instead of: "Tailing with invalid character...". Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> LKML-Reference: <1292854685-8230-7-git-send-email-fbuihuu@gmail.com> Signed-off-by: Franck Bui-Huu <fbuihuu@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/probe-event.c92
1 files changed, 60 insertions, 32 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 80cc0bc284fd..099336ed34b4 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -529,6 +529,19 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
529} 529}
530#endif 530#endif
531 531
532static int parse_line_num(char **ptr, int *val, const char *what)
533{
534 const char *start = *ptr;
535
536 errno = 0;
537 *val = strtol(*ptr, ptr, 0);
538 if (errno || *ptr == start) {
539 semantic_error("'%s' is not a valid number.\n", what);
540 return -EINVAL;
541 }
542 return 0;
543}
544
532/* 545/*
533 * Stuff 'lr' according to the line range described by 'arg'. 546 * Stuff 'lr' according to the line range described by 'arg'.
534 * The line range syntax is described by: 547 * The line range syntax is described by:
@@ -538,50 +551,65 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
538 */ 551 */
539int parse_line_range_desc(const char *arg, struct line_range *lr) 552int parse_line_range_desc(const char *arg, struct line_range *lr)
540{ 553{
541 const char *ptr; 554 char *range, *name = strdup(arg);
542 char *tmp; 555 int err;
556
557 if (!name)
558 return -ENOMEM;
559
560 lr->start = 0;
561 lr->end = INT_MAX;
562
563 range = strchr(name, ':');
564 if (range) {
565 *range++ = '\0';
566
567 err = parse_line_num(&range, &lr->start, "start line");
568 if (err)
569 goto err;
570
571 if (*range == '+' || *range == '-') {
572 const char c = *range++;
573
574 err = parse_line_num(&range, &lr->end, "end line");
575 if (err)
576 goto err;
577
578 if (c == '+') {
579 lr->end += lr->start;
580 /*
581 * Adjust the number of lines here.
582 * If the number of lines == 1, the
583 * the end of line should be equal to
584 * the start of line.
585 */
586 lr->end--;
587 }
588 }
543 589
544 ptr = strchr(arg, ':');
545 if (ptr) {
546 lr->start = (int)strtoul(ptr + 1, &tmp, 0);
547 if (*tmp == '+') {
548 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0);
549 lr->end--; /*
550 * Adjust the number of lines here.
551 * If the number of lines == 1, the
552 * the end of line should be equal to
553 * the start of line.
554 */
555 } else if (*tmp == '-')
556 lr->end = (int)strtoul(tmp + 1, &tmp, 0);
557 else
558 lr->end = INT_MAX;
559 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 590 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
591
592 err = -EINVAL;
560 if (lr->start > lr->end) { 593 if (lr->start > lr->end) {
561 semantic_error("Start line must be smaller" 594 semantic_error("Start line must be smaller"
562 " than end line.\n"); 595 " than end line.\n");
563 return -EINVAL; 596 goto err;
564 } 597 }
565 if (*tmp != '\0') { 598 if (*range != '\0') {
566 semantic_error("Tailing with invalid character '%d'.\n", 599 semantic_error("Tailing with invalid str '%s'.\n", range);
567 *tmp); 600 goto err;
568 return -EINVAL;
569 } 601 }
570 tmp = strndup(arg, (ptr - arg));
571 } else {
572 tmp = strdup(arg);
573 lr->end = INT_MAX;
574 } 602 }
575 603
576 if (tmp == NULL) 604 if (strchr(name, '.'))
577 return -ENOMEM; 605 lr->file = name;
578
579 if (strchr(tmp, '.'))
580 lr->file = tmp;
581 else 606 else
582 lr->function = tmp; 607 lr->function = name;
583 608
584 return 0; 609 return 0;
610err:
611 free(name);
612 return err;
585} 613}
586 614
587/* Check the name is good for event/group */ 615/* Check the name is good for event/group */