[BACK]Return to bt_parser.h CVS log [TXT][DIR] Up to [local] / src / usr.sbin / btrace

File: [local] / src / usr.sbin / btrace / bt_parser.h (download)

Revision 1.26, Sat Mar 30 07:41:45 2024 UTC (2 months, 1 week ago) by mpi
Branch: MAIN
CVS Tags: HEAD
Changes since 1.25: +9 -1 lines

Implement else branching logic including 'else if'.

Statement lists for if & else conditions are now wrapped in a new
'struct bt_cond'.  Handling B_AC_TEST statements moved to stmt_eval()
to handle nested conditional statements.

From Christian Ludwig christian_ludwig at genua.de

/*	$OpenBSD: bt_parser.h,v 1.26 2024/03/30 07:41:45 mpi Exp $	*/

/*
 * Copyright (c) 2019-2021 Martin Pieuchot <mpi@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef BT_PARSER_H
#define BT_PARSER_H

#ifndef nitems
#define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
#endif

/*
 * Probes represent entry points where events can be recorded.
 *
 * Those specified in a given bt(5) script are enabled at runtime. They
 * are represented as:
 *
 *	"provider:function:name"
 * or
 *	"provider:time_unit:rate"
 *
 * Multiple probes can be associated to the same action.
 */
struct bt_probe {
	SLIST_ENTRY(bt_probe)	 bp_next;	/* next probe for this rule */
	const char		*bp_prov;	/* provider */
	const char		*bp_func;	/* function or time unit */
	const char		*bp_name;
	uint32_t		 bp_rate;
#define bp_unit	bp_func
	enum bt_ptype {
		 B_PT_BEGIN = 1,
		 B_PT_END,
		 B_PT_PROBE,
	}			 bp_type;	/* BEGIN, END or 'probe' */
	void			*bp_cookie;	/* ioctl request */
	uint32_t		 bp_pbn;	/* ID assigned by the kernel */
};


/*
 * Event filters correspond to checks performed in-kernel.
 */
struct bt_evtfilter {
	int			bf_op;
	enum bt_filtervar {
		B_FV_NONE = 1,
		B_FV_PID,
		B_FV_TID
	}			 bf_var;
	uint32_t		 bf_val;
};

/*
 * Filters, also known as predicates, describe under which set of
 * conditions a rule is executed.
 *
 * They are performed when a rule is evaluated and events might be
 * discarded at runtime.
 */
struct bt_filter {
	struct bt_stmt		 *bf_condition;	/* per event condition */
};

TAILQ_HEAD(bt_ruleq, bt_rule);

/*
 * A rule is the language representation of which 'action' to attach to
 * which 'probe' under which conditions ('filter').  In other words it
 * represents the following:
 *
 *	probe / filter / { action }
 */
struct bt_rule {
	TAILQ_ENTRY(bt_rule)	 br_next;	/* linkage in global list */
	SLIST_HEAD(, bt_probe)	 br_probes;	/* list of probes */
	struct bt_filter	*br_filter;
	SLIST_HEAD(, bt_stmt)	 br_action;
	SLIST_HEAD(, bt_var)	 br_variables;	/* local variables */
};

/*
 * Global and local variable representation.
 *
 * Variables are untyped and also include maps and histograms.
 */
struct bt_var {
	SLIST_ENTRY(bt_var)	 bv_next;	/* linkage in global list */
	const char		*bv_name;	/* name of the variable */
	struct bt_arg		*bv_value;	/* corresponding value */
	enum bt_vartype	{
		B_VT_STR = 1,
		B_VT_LONG,
		B_VT_TUPLE,
		B_VT_MAP,
		B_VT_HIST,
	}			 bv_type;
};

/*
 * Representation of an argument.
 *
 * A so called "argument" can be any symbol representing a value or
 * a combination of those through an operation.
 */
struct bt_arg {
	SLIST_ENTRY(bt_arg)	 ba_next;
	void			*ba_value;
	struct bt_arg		*ba_key;	/* key for maps/histograms */
	enum bt_argtype {
		B_AT_STR = 1,			/* C-style string */
		B_AT_LONG,			/* Number (integer) */
		B_AT_VAR,			/* global/local variable */
		B_AT_MAP,			/* global map (@map[]) */
		B_AT_HIST,			/* histogram */
		B_AT_TUPLE,			/* tuple (1, 42, "str") */
		B_AT_TMEMBER,			/* tuple member $t.2 */
		B_AT_NIL,			/* empty value */

		B_AT_BI_PID,
		B_AT_BI_TID,
		B_AT_BI_COMM,
		B_AT_BI_CPU,
		B_AT_BI_NSECS,
		B_AT_BI_KSTACK,
		B_AT_BI_USTACK,
		B_AT_BI_ARG0,
		B_AT_BI_ARG1,
		B_AT_BI_ARG2,
		B_AT_BI_ARG3,
		B_AT_BI_ARG4,
		B_AT_BI_ARG5,
		B_AT_BI_ARG6,
		B_AT_BI_ARG7,
		B_AT_BI_ARG8,
		B_AT_BI_ARG9,
		B_AT_BI_ARGS,
		B_AT_BI_RETVAL,
		B_AT_BI_PROBE,

		B_AT_FN_STR,			/* str($1); str($1, 3); */

		B_AT_MF_COUNT,			/* @map[key] = count() */
		B_AT_MF_MAX,			/* @map[key] = max(nsecs) */
		B_AT_MF_MIN,			/* @map[key] = min(pid) */
		B_AT_MF_SUM,			/* @map[key] = sum(@elapsed) */

		B_AT_OP_PLUS,
		B_AT_OP_MINUS,
		B_AT_OP_MULT,
		B_AT_OP_DIVIDE,
		B_AT_OP_MODULO,
		B_AT_OP_BAND,
		B_AT_OP_XOR,
		B_AT_OP_BOR,
		B_AT_OP_EQ,
		B_AT_OP_NE,
		B_AT_OP_LE,
		B_AT_OP_LT,
		B_AT_OP_GE,
		B_AT_OP_GT,
		B_AT_OP_LAND,
		B_AT_OP_LOR,
	}			 ba_type;
};

#define BA_INITIALIZER(v, t)	{ { NULL }, (void *)(v), NULL, (t) }

/*
 * Represents branches of an if-else statement.
 */
struct bt_cond {
	struct bt_stmt		*bc_condbs;
	struct bt_stmt		*bc_elsebs;
};

/*
 * Each action associated with a given probe is made of at least one
 * statement.
 *
 * Statements are interpreted linearly in userland to format data
 * recorded in the form of events.
 */
struct bt_stmt {
	SLIST_ENTRY(bt_stmt)	 bs_next;
	struct bt_var		*bs_var;	/* for STOREs */
	SLIST_HEAD(, bt_arg)	 bs_args;
	enum bt_action {
		B_AC_BUCKETIZE,			/* @h = hist(42) */
		B_AC_CLEAR,			/* clear(@map) */
		B_AC_DELETE,			/* delete(@map[key]) */
		B_AC_EXIT,			/* exit() */
		B_AC_INSERT,			/* @map[key] = 42 */
		B_AC_PRINT,			/* print(@map, 10) */
		B_AC_PRINTF,			/* printf("hello!\n") */
		B_AC_STORE,			/* @a = 3 */
		B_AC_TEST,			/* if (@a) */
		B_AC_TIME,			/* time("%H:%M:%S  ") */
		B_AC_ZERO,			/* zero(@map) */
	}			 bs_act;
};

extern struct bt_ruleq	 g_rules;	/* Successfully parsed rules. */
extern int		 g_nprobes;	/* # of probes to attach */
extern struct bt_arg 	 g_nullba;
extern struct bt_arg	 g_maxba;

int			 btparse(const char *, size_t, const char *, int);

#define ba_new(v, t)	 ba_new0((void *)(v), (t))
struct bt_arg		*ba_new0(void *, enum bt_argtype);

const char		*bv_name(struct bt_var *);

#endif /* BT_PARSER_H */