xref: /openbsd-src/usr.sbin/btrace/bt_parser.h (revision 139d07b5d2b54520acbf93ed1ea9df2b42a216fe)
1*139d07b5Smpi /*	$OpenBSD: bt_parser.h,v 1.27 2025/01/23 11:17:32 mpi Exp $	*/
223160851Smpi 
323160851Smpi /*
4ea0c567aSmpi  * Copyright (c) 2019-2021 Martin Pieuchot <mpi@openbsd.org>
523160851Smpi  *
623160851Smpi  * Permission to use, copy, modify, and distribute this software for any
723160851Smpi  * purpose with or without fee is hereby granted, provided that the above
823160851Smpi  * copyright notice and this permission notice appear in all copies.
923160851Smpi  *
1023160851Smpi  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1123160851Smpi  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1223160851Smpi  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1323160851Smpi  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1423160851Smpi  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1523160851Smpi  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1623160851Smpi  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1723160851Smpi  */
1823160851Smpi 
1923160851Smpi #ifndef BT_PARSER_H
2023160851Smpi #define BT_PARSER_H
2123160851Smpi 
2223160851Smpi #ifndef nitems
2323160851Smpi #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
2423160851Smpi #endif
2523160851Smpi 
2623160851Smpi /*
2712999ef2Smpi  * Probes represent entry points where events can be recorded.
2812999ef2Smpi  *
2912999ef2Smpi  * Those specified in a given bt(5) script are enabled at runtime. They
3012999ef2Smpi  * are represented as:
3123160851Smpi  *
3223160851Smpi  *	"provider:function:name"
3323160851Smpi  * or
34*139d07b5Smpi  *	"provider:time_unit:number"
351694fc34Smpi  *
361694fc34Smpi  * Multiple probes can be associated to the same action.
3723160851Smpi  */
3823160851Smpi struct bt_probe {
391694fc34Smpi 	SLIST_ENTRY(bt_probe)	 bp_next;	/* next probe for this rule */
4023160851Smpi 	const char		*bp_prov;	/* provider */
4123160851Smpi 	const char		*bp_func;	/* function or time unit */
4223160851Smpi 	const char		*bp_name;
43*139d07b5Smpi 	uint64_t		 bp_nsecs;
4423160851Smpi #define bp_unit	bp_func
451694fc34Smpi 	enum bt_ptype {
461694fc34Smpi 		 B_PT_BEGIN = 1,
471694fc34Smpi 		 B_PT_END,
481694fc34Smpi 		 B_PT_PROBE,
491694fc34Smpi 	}			 bp_type;	/* BEGIN, END or 'probe' */
501694fc34Smpi 	void			*bp_cookie;	/* ioctl request */
511694fc34Smpi 	uint32_t		 bp_pbn;	/* ID assigned by the kernel */
5223160851Smpi };
5323160851Smpi 
54ea0c567aSmpi 
5523160851Smpi /*
56ea0c567aSmpi  * Event filters correspond to checks performed in-kernel.
5723160851Smpi  */
58ea0c567aSmpi struct bt_evtfilter {
59a31d03f7Smpi 	int			bf_op;
6023160851Smpi 	enum bt_filtervar {
6123160851Smpi 		B_FV_NONE = 1,
6223160851Smpi 		B_FV_PID,
6323160851Smpi 		B_FV_TID
6423160851Smpi 	}			 bf_var;
6523160851Smpi 	uint32_t		 bf_val;
6623160851Smpi };
6723160851Smpi 
68ea0c567aSmpi /*
69ea0c567aSmpi  * Filters, also known as predicates, describe under which set of
70ea0c567aSmpi  * conditions a rule is executed.
71ea0c567aSmpi  *
72466f7318Smpi  * They are performed when a rule is evaluated and events might be
73466f7318Smpi  * discarded at runtime.
74ea0c567aSmpi  */
75ea0c567aSmpi struct bt_filter {
76ea0c567aSmpi 	struct bt_stmt		 *bf_condition;	/* per event condition */
77ea0c567aSmpi };
78ea0c567aSmpi 
7923160851Smpi TAILQ_HEAD(bt_ruleq, bt_rule);
8023160851Smpi 
8123160851Smpi /*
8223160851Smpi  * A rule is the language representation of which 'action' to attach to
8323160851Smpi  * which 'probe' under which conditions ('filter').  In other words it
8423160851Smpi  * represents the following:
8523160851Smpi  *
8623160851Smpi  *	probe / filter / { action }
8723160851Smpi  */
8823160851Smpi struct bt_rule {
8923160851Smpi 	TAILQ_ENTRY(bt_rule)	 br_next;	/* linkage in global list */
901694fc34Smpi 	SLIST_HEAD(, bt_probe)	 br_probes;	/* list of probes */
9123160851Smpi 	struct bt_filter	*br_filter;
9223160851Smpi 	SLIST_HEAD(, bt_stmt)	 br_action;
937aa3827dSmpi 	SLIST_HEAD(, bt_var)	 br_variables;	/* local variables */
9423160851Smpi };
9523160851Smpi 
9623160851Smpi /*
9766f34ae4Smpi  * Global and local variable representation.
9812999ef2Smpi  *
9912999ef2Smpi  * Variables are untyped and also include maps and histograms.
10023160851Smpi  */
10123160851Smpi struct bt_var {
10223160851Smpi 	SLIST_ENTRY(bt_var)	 bv_next;	/* linkage in global list */
10323160851Smpi 	const char		*bv_name;	/* name of the variable */
10423160851Smpi 	struct bt_arg		*bv_value;	/* corresponding value */
105d2392c66Smpi 	enum bt_vartype	{
106d2392c66Smpi 		B_VT_STR = 1,
107d2392c66Smpi 		B_VT_LONG,
10866f34ae4Smpi 		B_VT_TUPLE,
109d2392c66Smpi 		B_VT_MAP,
110d2392c66Smpi 		B_VT_HIST,
111d2392c66Smpi 	}			 bv_type;
11223160851Smpi };
11323160851Smpi 
11423160851Smpi /*
1153a50f0a9Sjmc  * Representation of an argument.
11623160851Smpi  *
11723160851Smpi  * A so called "argument" can be any symbol representing a value or
11823160851Smpi  * a combination of those through an operation.
11923160851Smpi  */
12023160851Smpi struct bt_arg {
12123160851Smpi 	SLIST_ENTRY(bt_arg)	 ba_next;
12223160851Smpi 	void			*ba_value;
1239c84395dSmpi 	struct bt_arg		*ba_key;	/* key for maps/histograms */
12423160851Smpi 	enum bt_argtype {
12523160851Smpi 		B_AT_STR = 1,			/* C-style string */
12623160851Smpi 		B_AT_LONG,			/* Number (integer) */
1277aa3827dSmpi 		B_AT_VAR,			/* global/local variable */
12888be68dbSmpi 		B_AT_MAP,			/* global map (@map[]) */
1299c84395dSmpi 		B_AT_HIST,			/* histogram */
13066f34ae4Smpi 		B_AT_TUPLE,			/* tuple (1, 42, "str") */
13166f34ae4Smpi 		B_AT_TMEMBER,			/* tuple member $t.2 */
13258afdee7Sdv 		B_AT_NIL,			/* empty value */
13323160851Smpi 
13423160851Smpi 		B_AT_BI_PID,
13523160851Smpi 		B_AT_BI_TID,
13623160851Smpi 		B_AT_BI_COMM,
1370948ba6cSmpi 		B_AT_BI_CPU,
13823160851Smpi 		B_AT_BI_NSECS,
13923160851Smpi 		B_AT_BI_KSTACK,
14023160851Smpi 		B_AT_BI_USTACK,
14123160851Smpi 		B_AT_BI_ARG0,
14223160851Smpi 		B_AT_BI_ARG1,
14323160851Smpi 		B_AT_BI_ARG2,
14423160851Smpi 		B_AT_BI_ARG3,
14523160851Smpi 		B_AT_BI_ARG4,
14623160851Smpi 		B_AT_BI_ARG5,
14723160851Smpi 		B_AT_BI_ARG6,
14823160851Smpi 		B_AT_BI_ARG7,
14923160851Smpi 		B_AT_BI_ARG8,
15023160851Smpi 		B_AT_BI_ARG9,
15123160851Smpi 		B_AT_BI_ARGS,
15223160851Smpi 		B_AT_BI_RETVAL,
153ca210abeSclaudio 		B_AT_BI_PROBE,
15423160851Smpi 
155b005393aSdv 		B_AT_FN_STR,			/* str($1); str($1, 3); */
156b005393aSdv 
1570dac42ecSmpi 		B_AT_MF_COUNT,			/* @map[key] = count() */
1580dac42ecSmpi 		B_AT_MF_MAX,			/* @map[key] = max(nsecs) */
1590dac42ecSmpi 		B_AT_MF_MIN,			/* @map[key] = min(pid) */
1600dac42ecSmpi 		B_AT_MF_SUM,			/* @map[key] = sum(@elapsed) */
16123160851Smpi 
162a31d03f7Smpi 		B_AT_OP_PLUS,
16323160851Smpi 		B_AT_OP_MINUS,
16423160851Smpi 		B_AT_OP_MULT,
16523160851Smpi 		B_AT_OP_DIVIDE,
166b9c158acScheloha 		B_AT_OP_MODULO,
167a31d03f7Smpi 		B_AT_OP_BAND,
16889f39301Smpi 		B_AT_OP_XOR,
169a31d03f7Smpi 		B_AT_OP_BOR,
170a31d03f7Smpi 		B_AT_OP_EQ,
171a31d03f7Smpi 		B_AT_OP_NE,
172a31d03f7Smpi 		B_AT_OP_LE,
17325efc3b0Smpi 		B_AT_OP_LT,
174a31d03f7Smpi 		B_AT_OP_GE,
17525efc3b0Smpi 		B_AT_OP_GT,
176a31d03f7Smpi 		B_AT_OP_LAND,
177a31d03f7Smpi 		B_AT_OP_LOR,
17823160851Smpi 	}			 ba_type;
17923160851Smpi };
18023160851Smpi 
1819c84395dSmpi #define BA_INITIALIZER(v, t)	{ { NULL }, (void *)(v), NULL, (t) }
1829c84395dSmpi 
18323160851Smpi /*
184ca41b749Smpi  * Represents branches of an if-else statement.
185ca41b749Smpi  */
186ca41b749Smpi struct bt_cond {
187ca41b749Smpi 	struct bt_stmt		*bc_condbs;
188ca41b749Smpi 	struct bt_stmt		*bc_elsebs;
189ca41b749Smpi };
190ca41b749Smpi 
191ca41b749Smpi /*
19212999ef2Smpi  * Each action associated with a given probe is made of at least one
19312999ef2Smpi  * statement.
19412999ef2Smpi  *
19512999ef2Smpi  * Statements are interpreted linearly in userland to format data
19612999ef2Smpi  * recorded in the form of events.
19723160851Smpi  */
19823160851Smpi struct bt_stmt {
19923160851Smpi 	SLIST_ENTRY(bt_stmt)	 bs_next;
20023160851Smpi 	struct bt_var		*bs_var;	/* for STOREs */
20123160851Smpi 	SLIST_HEAD(, bt_arg)	 bs_args;
20223160851Smpi 	enum bt_action {
2039c84395dSmpi 		B_AC_BUCKETIZE,			/* @h = hist(42) */
20423160851Smpi 		B_AC_CLEAR,			/* clear(@map) */
20523160851Smpi 		B_AC_DELETE,			/* delete(@map[key]) */
20623160851Smpi 		B_AC_EXIT,			/* exit() */
2079c84395dSmpi 		B_AC_INSERT,			/* @map[key] = 42 */
20823160851Smpi 		B_AC_PRINT,			/* print(@map, 10) */
20923160851Smpi 		B_AC_PRINTF,			/* printf("hello!\n") */
2109c84395dSmpi 		B_AC_STORE,			/* @a = 3 */
211ea0c567aSmpi 		B_AC_TEST,			/* if (@a) */
212a378a2aaSmpi 		B_AC_TIME,			/* time("%H:%M:%S  ") */
21323160851Smpi 		B_AC_ZERO,			/* zero(@map) */
21423160851Smpi 	}			 bs_act;
21523160851Smpi };
21623160851Smpi 
21787df4deeSderaadt extern struct bt_ruleq	 g_rules;	/* Successfully parsed rules. */
21887df4deeSderaadt extern int		 g_nprobes;	/* # of probes to attach */
21989f39301Smpi extern struct bt_arg 	 g_nullba;
22089f39301Smpi extern struct bt_arg	 g_maxba;
22123160851Smpi 
22223160851Smpi int			 btparse(const char *, size_t, const char *, int);
22323160851Smpi 
22423160851Smpi #define ba_new(v, t)	 ba_new0((void *)(v), (t))
22523160851Smpi struct bt_arg		*ba_new0(void *, enum bt_argtype);
22623160851Smpi 
227477314cbSmpi const char		*bv_name(struct bt_var *);
228477314cbSmpi 
22923160851Smpi #endif /* BT_PARSER_H */
230