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