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