diff options
Diffstat (limited to 'tools/perf/util/callchain.c')
-rw-r--r-- | tools/perf/util/callchain.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 08f0fbf5527c..ba7297230143 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -25,6 +25,90 @@ | |||
25 | 25 | ||
26 | __thread struct callchain_cursor callchain_cursor; | 26 | __thread struct callchain_cursor callchain_cursor; |
27 | 27 | ||
28 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
29 | static int get_stack_size(const char *str, unsigned long *_size) | ||
30 | { | ||
31 | char *endptr; | ||
32 | unsigned long size; | ||
33 | unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); | ||
34 | |||
35 | size = strtoul(str, &endptr, 0); | ||
36 | |||
37 | do { | ||
38 | if (*endptr) | ||
39 | break; | ||
40 | |||
41 | size = round_up(size, sizeof(u64)); | ||
42 | if (!size || size > max_size) | ||
43 | break; | ||
44 | |||
45 | *_size = size; | ||
46 | return 0; | ||
47 | |||
48 | } while (0); | ||
49 | |||
50 | pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", | ||
51 | max_size, str); | ||
52 | return -1; | ||
53 | } | ||
54 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ | ||
55 | |||
56 | int parse_callchain_record_opt(const char *arg) | ||
57 | { | ||
58 | char *tok, *name, *saveptr = NULL; | ||
59 | char *buf; | ||
60 | int ret = -1; | ||
61 | |||
62 | /* We need buffer that we know we can write to. */ | ||
63 | buf = malloc(strlen(arg) + 1); | ||
64 | if (!buf) | ||
65 | return -ENOMEM; | ||
66 | |||
67 | strcpy(buf, arg); | ||
68 | |||
69 | tok = strtok_r((char *)buf, ",", &saveptr); | ||
70 | name = tok ? : (char *)buf; | ||
71 | |||
72 | do { | ||
73 | /* Framepointer style */ | ||
74 | if (!strncmp(name, "fp", sizeof("fp"))) { | ||
75 | if (!strtok_r(NULL, ",", &saveptr)) { | ||
76 | callchain_param.record_mode = CALLCHAIN_FP; | ||
77 | ret = 0; | ||
78 | } else | ||
79 | pr_err("callchain: No more arguments " | ||
80 | "needed for -g fp\n"); | ||
81 | break; | ||
82 | |||
83 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
84 | /* Dwarf style */ | ||
85 | } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { | ||
86 | const unsigned long default_stack_dump_size = 8192; | ||
87 | |||
88 | ret = 0; | ||
89 | callchain_param.record_mode = CALLCHAIN_DWARF; | ||
90 | callchain_param.dump_size = default_stack_dump_size; | ||
91 | |||
92 | tok = strtok_r(NULL, ",", &saveptr); | ||
93 | if (tok) { | ||
94 | unsigned long size = 0; | ||
95 | |||
96 | ret = get_stack_size(tok, &size); | ||
97 | callchain_param.dump_size = size; | ||
98 | } | ||
99 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ | ||
100 | } else { | ||
101 | pr_err("callchain: Unknown --call-graph option " | ||
102 | "value: %s\n", arg); | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | } while (0); | ||
107 | |||
108 | free(buf); | ||
109 | return ret; | ||
110 | } | ||
111 | |||
28 | int | 112 | int |
29 | parse_callchain_report_opt(const char *arg) | 113 | parse_callchain_report_opt(const char *arg) |
30 | { | 114 | { |