brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · f7f7aff Raw
116 lines · c
1// SPDX-License-Identifier: GPL-2.02#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("no_flags", PERF_SAMPLE_BRANCH_NO_FLAGS),34	BRANCH_OPT("no_cycles", PERF_SAMPLE_BRANCH_NO_CYCLES),35	BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE),36	BRANCH_OPT("stack", PERF_SAMPLE_BRANCH_CALL_STACK),37	BRANCH_OPT("hw_index", PERF_SAMPLE_BRANCH_HW_INDEX),38	BRANCH_OPT("priv", PERF_SAMPLE_BRANCH_PRIV_SAVE),39	BRANCH_OPT("counter", PERF_SAMPLE_BRANCH_COUNTERS),40	BRANCH_END41};42 43int parse_branch_str(const char *str, __u64 *mode)44{45#define ONLY_PLM \46	(PERF_SAMPLE_BRANCH_USER	|\47	 PERF_SAMPLE_BRANCH_KERNEL	|\48	 PERF_SAMPLE_BRANCH_HV)49 50	int ret = 0;51	char *p, *s;52	char *os = NULL;53	const struct branch_mode *br;54 55	if (str == NULL) {56		*mode = PERF_SAMPLE_BRANCH_ANY;57		return 0;58	}59 60	/* because str is read-only */61	s = os = strdup(str);62	if (!s)63		return -1;64 65	for (;;) {66		p = strchr(s, ',');67		if (p)68			*p = '\0';69 70		for (br = branch_modes; br->name; br++) {71			if (!strcasecmp(s, br->name))72				break;73		}74		if (!br->name) {75			ret = -1;76			pr_warning("unknown branch filter %s,"77				    " check man page\n", s);78			goto error;79		}80 81		*mode |= br->mode;82 83		if (!p)84			break;85 86		s = p + 1;87	}88 89	/* default to any branch */90	if ((*mode & ~ONLY_PLM) == 0) {91		*mode = PERF_SAMPLE_BRANCH_ANY;92	}93error:94	free(os);95	return ret;96}97 98int99parse_branch_stack(const struct option *opt, const char *str, int unset)100{101	__u64 *mode = (__u64 *)opt->value;102 103	if (unset)104		return 0;105 106	/*107	 * cannot set it twice, -b + --branch-filter for instance108	 */109	if (*mode) {110		pr_err("Error: Can't use --branch-any (-b) with --branch-filter (-j).\n");111		return -1;112	}113 114	return parse_branch_str(str, mode);115}116