0001
0002 #include <stdbool.h>
0003 #include <stdlib.h>
0004 #include <stdint.h>
0005 #include <string.h>
0006 #include <stdio.h>
0007 #include "util/debug.h"
0008 #include <subcmd/parse-options.h>
0009 #include "util/perf_regs.h"
0010 #include "util/parse-regs-options.h"
0011
0012 static int
0013 __parse_regs(const struct option *opt, const char *str, int unset, bool intr)
0014 {
0015 uint64_t *mode = (uint64_t *)opt->value;
0016 const struct sample_reg *r = NULL;
0017 char *s, *os = NULL, *p;
0018 int ret = -1;
0019 uint64_t mask;
0020
0021 if (unset)
0022 return 0;
0023
0024
0025
0026
0027 if (*mode)
0028 return -1;
0029
0030 if (intr)
0031 mask = arch__intr_reg_mask();
0032 else
0033 mask = arch__user_reg_mask();
0034
0035
0036 if (str) {
0037
0038 s = os = strdup(str);
0039 if (!s)
0040 return -1;
0041
0042 for (;;) {
0043 p = strchr(s, ',');
0044 if (p)
0045 *p = '\0';
0046
0047 if (!strcmp(s, "?")) {
0048 fprintf(stderr, "available registers: ");
0049 #ifdef HAVE_PERF_REGS_SUPPORT
0050 for (r = sample_reg_masks; r->name; r++) {
0051 if (r->mask & mask)
0052 fprintf(stderr, "%s ", r->name);
0053 }
0054 #endif
0055 fputc('\n', stderr);
0056
0057 goto error;
0058 }
0059 #ifdef HAVE_PERF_REGS_SUPPORT
0060 for (r = sample_reg_masks; r->name; r++) {
0061 if ((r->mask & mask) && !strcasecmp(s, r->name))
0062 break;
0063 }
0064 #endif
0065 if (!r || !r->name) {
0066 ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n",
0067 s, intr ? "-I" : "--user-regs=");
0068 goto error;
0069 }
0070
0071 *mode |= r->mask;
0072
0073 if (!p)
0074 break;
0075
0076 s = p + 1;
0077 }
0078 }
0079 ret = 0;
0080
0081
0082 if (*mode == 0)
0083 *mode = mask;
0084 error:
0085 free(os);
0086 return ret;
0087 }
0088
0089 int
0090 parse_user_regs(const struct option *opt, const char *str, int unset)
0091 {
0092 return __parse_regs(opt, str, unset, false);
0093 }
0094
0095 int
0096 parse_intr_regs(const struct option *opt, const char *str, int unset)
0097 {
0098 return __parse_regs(opt, str, unset, true);
0099 }