1 // SPDX-License-Identifier: GPL-2.0 2 #include "perf.h" 3 #include "util/debug.h" 4 #include <subcmd/parse-options.h> 5 #include "util/parse-branch-options.h" 6 #include <stdlib.h> 7 8 #define BRANCH_OPT(n, m) \ 9 { .name = n, .mode = (m) } 10 11 #define BRANCH_END { .name = NULL } 12 13 struct branch_mode { 14 const char *name; 15 int mode; 16 }; 17 18 static const struct branch_mode branch_modes[] = { 19 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 20 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 21 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 22 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 23 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 24 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 25 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 26 BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 27 BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 28 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 29 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), 30 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP), 31 BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL), 32 BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE), 33 BRANCH_END 34 }; 35 36 int parse_branch_str(const char *str, __u64 *mode) 37 { 38 #define ONLY_PLM \ 39 (PERF_SAMPLE_BRANCH_USER |\ 40 PERF_SAMPLE_BRANCH_KERNEL |\ 41 PERF_SAMPLE_BRANCH_HV) 42 43 int ret = 0; 44 char *p, *s; 45 char *os = NULL; 46 const struct branch_mode *br; 47 48 if (str == NULL) { 49 *mode = PERF_SAMPLE_BRANCH_ANY; 50 return 0; 51 } 52 53 /* because str is read-only */ 54 s = os = strdup(str); 55 if (!s) 56 return -1; 57 58 for (;;) { 59 p = strchr(s, ','); 60 if (p) 61 *p = '\0'; 62 63 for (br = branch_modes; br->name; br++) { 64 if (!strcasecmp(s, br->name)) 65 break; 66 } 67 if (!br->name) { 68 ret = -1; 69 pr_warning("unknown branch filter %s," 70 " check man page\n", s); 71 goto error; 72 } 73 74 *mode |= br->mode; 75 76 if (!p) 77 break; 78 79 s = p + 1; 80 } 81 82 /* default to any branch */ 83 if ((*mode & ~ONLY_PLM) == 0) { 84 *mode = PERF_SAMPLE_BRANCH_ANY; 85 } 86 error: 87 free(os); 88 return ret; 89 } 90 91 int 92 parse_branch_stack(const struct option *opt, const char *str, int unset) 93 { 94 __u64 *mode = (__u64 *)opt->value; 95 96 if (unset) 97 return 0; 98 99 /* 100 * cannot set it twice, -b + --branch-filter for instance 101 */ 102 if (*mode) 103 return -1; 104 105 return parse_branch_str(str, mode); 106 } 107