diff options
Diffstat (limited to 'tools/perf/util/util.c')
-rw-r--r-- | tools/perf/util/util.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index edc2d633b332..f7adf1203df1 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -566,6 +566,96 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags) | |||
566 | return (unsigned long) -1; | 566 | return (unsigned long) -1; |
567 | } | 567 | } |
568 | 568 | ||
569 | int get_stack_size(const char *str, unsigned long *_size) | ||
570 | { | ||
571 | char *endptr; | ||
572 | unsigned long size; | ||
573 | unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); | ||
574 | |||
575 | size = strtoul(str, &endptr, 0); | ||
576 | |||
577 | do { | ||
578 | if (*endptr) | ||
579 | break; | ||
580 | |||
581 | size = round_up(size, sizeof(u64)); | ||
582 | if (!size || size > max_size) | ||
583 | break; | ||
584 | |||
585 | *_size = size; | ||
586 | return 0; | ||
587 | |||
588 | } while (0); | ||
589 | |||
590 | pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", | ||
591 | max_size, str); | ||
592 | return -1; | ||
593 | } | ||
594 | |||
595 | int parse_callchain_record(const char *arg, struct callchain_param *param) | ||
596 | { | ||
597 | char *tok, *name, *saveptr = NULL; | ||
598 | char *buf; | ||
599 | int ret = -1; | ||
600 | |||
601 | /* We need buffer that we know we can write to. */ | ||
602 | buf = malloc(strlen(arg) + 1); | ||
603 | if (!buf) | ||
604 | return -ENOMEM; | ||
605 | |||
606 | strcpy(buf, arg); | ||
607 | |||
608 | tok = strtok_r((char *)buf, ",", &saveptr); | ||
609 | name = tok ? : (char *)buf; | ||
610 | |||
611 | do { | ||
612 | /* Framepointer style */ | ||
613 | if (!strncmp(name, "fp", sizeof("fp"))) { | ||
614 | if (!strtok_r(NULL, ",", &saveptr)) { | ||
615 | param->record_mode = CALLCHAIN_FP; | ||
616 | ret = 0; | ||
617 | } else | ||
618 | pr_err("callchain: No more arguments " | ||
619 | "needed for --call-graph fp\n"); | ||
620 | break; | ||
621 | |||
622 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
623 | /* Dwarf style */ | ||
624 | } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { | ||
625 | const unsigned long default_stack_dump_size = 8192; | ||
626 | |||
627 | ret = 0; | ||
628 | param->record_mode = CALLCHAIN_DWARF; | ||
629 | param->dump_size = default_stack_dump_size; | ||
630 | |||
631 | tok = strtok_r(NULL, ",", &saveptr); | ||
632 | if (tok) { | ||
633 | unsigned long size = 0; | ||
634 | |||
635 | ret = get_stack_size(tok, &size); | ||
636 | param->dump_size = size; | ||
637 | } | ||
638 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ | ||
639 | } else if (!strncmp(name, "lbr", sizeof("lbr"))) { | ||
640 | if (!strtok_r(NULL, ",", &saveptr)) { | ||
641 | param->record_mode = CALLCHAIN_LBR; | ||
642 | ret = 0; | ||
643 | } else | ||
644 | pr_err("callchain: No more arguments " | ||
645 | "needed for --call-graph lbr\n"); | ||
646 | break; | ||
647 | } else { | ||
648 | pr_err("callchain: Unknown --call-graph option " | ||
649 | "value: %s\n", arg); | ||
650 | break; | ||
651 | } | ||
652 | |||
653 | } while (0); | ||
654 | |||
655 | free(buf); | ||
656 | return ret; | ||
657 | } | ||
658 | |||
569 | int filename__read_str(const char *filename, char **buf, size_t *sizep) | 659 | int filename__read_str(const char *filename, char **buf, size_t *sizep) |
570 | { | 660 | { |
571 | size_t size = 0, alloc_size = 0; | 661 | size_t size = 0, alloc_size = 0; |