linux/tools/perf/util/parse-regs-options.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <stdbool.h>
   3#include <stdlib.h>
   4#include <stdint.h>
   5#include <string.h>
   6#include <stdio.h>
   7#include "util/debug.h"
   8#include <subcmd/parse-options.h>
   9#include "util/perf_regs.h"
  10#include "util/parse-regs-options.h"
  11
  12static int
  13__parse_regs(const struct option *opt, const char *str, int unset, bool intr)
  14{
  15        uint64_t *mode = (uint64_t *)opt->value;
  16        const struct sample_reg *r = NULL;
  17        char *s, *os = NULL, *p;
  18        int ret = -1;
  19        uint64_t mask;
  20
  21        if (unset)
  22                return 0;
  23
  24        /*
  25         * cannot set it twice
  26         */
  27        if (*mode)
  28                return -1;
  29
  30        if (intr)
  31                mask = arch__intr_reg_mask();
  32        else
  33                mask = arch__user_reg_mask();
  34
  35        /* str may be NULL in case no arg is passed to -I */
  36        if (str) {
  37                /* because str is read-only */
  38                s = os = strdup(str);
  39                if (!s)
  40                        return -1;
  41
  42                for (;;) {
  43                        p = strchr(s, ',');
  44                        if (p)
  45                                *p = '\0';
  46
  47                        if (!strcmp(s, "?")) {
  48                                fprintf(stderr, "available registers: ");
  49#ifdef HAVE_PERF_REGS_SUPPORT
  50                                for (r = sample_reg_masks; r->name; r++) {
  51                                        if (r->mask & mask)
  52                                                fprintf(stderr, "%s ", r->name);
  53                                }
  54#endif
  55                                fputc('\n', stderr);
  56                                /* just printing available regs */
  57                                return -1;
  58                        }
  59#ifdef HAVE_PERF_REGS_SUPPORT
  60                        for (r = sample_reg_masks; r->name; r++) {
  61                                if ((r->mask & mask) && !strcasecmp(s, r->name))
  62                                        break;
  63                        }
  64#endif
  65                        if (!r || !r->name) {
  66                                ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n",
  67                                            s, intr ? "-I" : "--user-regs=");
  68                                goto error;
  69                        }
  70
  71                        *mode |= r->mask;
  72
  73                        if (!p)
  74                                break;
  75
  76                        s = p + 1;
  77                }
  78        }
  79        ret = 0;
  80
  81        /* default to all possible regs */
  82        if (*mode == 0)
  83                *mode = mask;
  84error:
  85        free(os);
  86        return ret;
  87}
  88
  89int
  90parse_user_regs(const struct option *opt, const char *str, int unset)
  91{
  92        return __parse_regs(opt, str, unset, false);
  93}
  94
  95int
  96parse_intr_regs(const struct option *opt, const char *str, int unset)
  97{
  98        return __parse_regs(opt, str, unset, true);
  99}
 100