0001
0002 #include "util/debug.h"
0003 #include "util/event.h"
0004 #include <subcmd/parse-options.h>
0005 #include "util/parse-branch-options.h"
0006 #include <stdlib.h>
0007 #include <string.h>
0008
0009 #define BRANCH_OPT(n, m) \
0010 { .name = n, .mode = (m) }
0011
0012 #define BRANCH_END { .name = NULL }
0013
0014 struct branch_mode {
0015 const char *name;
0016 int mode;
0017 };
0018
0019 static const struct branch_mode branch_modes[] = {
0020 BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
0021 BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
0022 BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
0023 BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
0024 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
0025 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
0026 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
0027 BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
0028 BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
0029 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
0030 BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
0031 BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
0032 BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL),
0033 BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE),
0034 BRANCH_OPT("stack", PERF_SAMPLE_BRANCH_CALL_STACK),
0035 BRANCH_END
0036 };
0037
0038 int parse_branch_str(const char *str, __u64 *mode)
0039 {
0040 #define ONLY_PLM \
0041 (PERF_SAMPLE_BRANCH_USER |\
0042 PERF_SAMPLE_BRANCH_KERNEL |\
0043 PERF_SAMPLE_BRANCH_HV)
0044
0045 int ret = 0;
0046 char *p, *s;
0047 char *os = NULL;
0048 const struct branch_mode *br;
0049
0050 if (str == NULL) {
0051 *mode = PERF_SAMPLE_BRANCH_ANY;
0052 return 0;
0053 }
0054
0055
0056 s = os = strdup(str);
0057 if (!s)
0058 return -1;
0059
0060 for (;;) {
0061 p = strchr(s, ',');
0062 if (p)
0063 *p = '\0';
0064
0065 for (br = branch_modes; br->name; br++) {
0066 if (!strcasecmp(s, br->name))
0067 break;
0068 }
0069 if (!br->name) {
0070 ret = -1;
0071 pr_warning("unknown branch filter %s,"
0072 " check man page\n", s);
0073 goto error;
0074 }
0075
0076 *mode |= br->mode;
0077
0078 if (!p)
0079 break;
0080
0081 s = p + 1;
0082 }
0083
0084
0085 if ((*mode & ~ONLY_PLM) == 0) {
0086 *mode = PERF_SAMPLE_BRANCH_ANY;
0087 }
0088 error:
0089 free(os);
0090 return ret;
0091 }
0092
0093 int
0094 parse_branch_stack(const struct option *opt, const char *str, int unset)
0095 {
0096 __u64 *mode = (__u64 *)opt->value;
0097
0098 if (unset)
0099 return 0;
0100
0101
0102
0103
0104 if (*mode)
0105 return -1;
0106
0107 return parse_branch_str(str, mode);
0108 }