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 12 static 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 goto error; 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; 84 error: 85 free(os); 86 return ret; 87 } 88 89 int 90 parse_user_regs(const struct option *opt, const char *str, int unset) 91 { 92 return __parse_regs(opt, str, unset, false); 93 } 94 95 int 96 parse_intr_regs(const struct option *opt, const char *str, int unset) 97 { 98 return __parse_regs(opt, str, unset, true); 99 } 100