xref: /openbsd/usr.sbin/btrace/bt_parser.h (revision 139d07b5)
1 /*	$OpenBSD: bt_parser.h,v 1.27 2025/01/23 11:17:32 mpi Exp $	*/
2 
3 /*
4  * Copyright (c) 2019-2021 Martin Pieuchot <mpi@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef BT_PARSER_H
20 #define BT_PARSER_H
21 
22 #ifndef nitems
23 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
24 #endif
25 
26 /*
27  * Probes represent entry points where events can be recorded.
28  *
29  * Those specified in a given bt(5) script are enabled at runtime. They
30  * are represented as:
31  *
32  *	"provider:function:name"
33  * or
34  *	"provider:time_unit:number"
35  *
36  * Multiple probes can be associated to the same action.
37  */
38 struct bt_probe {
39 	SLIST_ENTRY(bt_probe)	 bp_next;	/* next probe for this rule */
40 	const char		*bp_prov;	/* provider */
41 	const char		*bp_func;	/* function or time unit */
42 	const char		*bp_name;
43 	uint64_t		 bp_nsecs;
44 #define bp_unit	bp_func
45 	enum bt_ptype {
46 		 B_PT_BEGIN = 1,
47 		 B_PT_END,
48 		 B_PT_PROBE,
49 	}			 bp_type;	/* BEGIN, END or 'probe' */
50 	void			*bp_cookie;	/* ioctl request */
51 	uint32_t		 bp_pbn;	/* ID assigned by the kernel */
52 };
53 
54 
55 /*
56  * Event filters correspond to checks performed in-kernel.
57  */
58 struct bt_evtfilter {
59 	int			bf_op;
60 	enum bt_filtervar {
61 		B_FV_NONE = 1,
62 		B_FV_PID,
63 		B_FV_TID
64 	}			 bf_var;
65 	uint32_t		 bf_val;
66 };
67 
68 /*
69  * Filters, also known as predicates, describe under which set of
70  * conditions a rule is executed.
71  *
72  * They are performed when a rule is evaluated and events might be
73  * discarded at runtime.
74  */
75 struct bt_filter {
76 	struct bt_stmt		 *bf_condition;	/* per event condition */
77 };
78 
79 TAILQ_HEAD(bt_ruleq, bt_rule);
80 
81 /*
82  * A rule is the language representation of which 'action' to attach to
83  * which 'probe' under which conditions ('filter').  In other words it
84  * represents the following:
85  *
86  *	probe / filter / { action }
87  */
88 struct bt_rule {
89 	TAILQ_ENTRY(bt_rule)	 br_next;	/* linkage in global list */
90 	SLIST_HEAD(, bt_probe)	 br_probes;	/* list of probes */
91 	struct bt_filter	*br_filter;
92 	SLIST_HEAD(, bt_stmt)	 br_action;
93 	SLIST_HEAD(, bt_var)	 br_variables;	/* local variables */
94 };
95 
96 /*
97  * Global and local variable representation.
98  *
99  * Variables are untyped and also include maps and histograms.
100  */
101 struct bt_var {
102 	SLIST_ENTRY(bt_var)	 bv_next;	/* linkage in global list */
103 	const char		*bv_name;	/* name of the variable */
104 	struct bt_arg		*bv_value;	/* corresponding value */
105 	enum bt_vartype	{
106 		B_VT_STR = 1,
107 		B_VT_LONG,
108 		B_VT_TUPLE,
109 		B_VT_MAP,
110 		B_VT_HIST,
111 	}			 bv_type;
112 };
113 
114 /*
115  * Representation of an argument.
116  *
117  * A so called "argument" can be any symbol representing a value or
118  * a combination of those through an operation.
119  */
120 struct bt_arg {
121 	SLIST_ENTRY(bt_arg)	 ba_next;
122 	void			*ba_value;
123 	struct bt_arg		*ba_key;	/* key for maps/histograms */
124 	enum bt_argtype {
125 		B_AT_STR = 1,			/* C-style string */
126 		B_AT_LONG,			/* Number (integer) */
127 		B_AT_VAR,			/* global/local variable */
128 		B_AT_MAP,			/* global map (@map[]) */
129 		B_AT_HIST,			/* histogram */
130 		B_AT_TUPLE,			/* tuple (1, 42, "str") */
131 		B_AT_TMEMBER,			/* tuple member $t.2 */
132 		B_AT_NIL,			/* empty value */
133 
134 		B_AT_BI_PID,
135 		B_AT_BI_TID,
136 		B_AT_BI_COMM,
137 		B_AT_BI_CPU,
138 		B_AT_BI_NSECS,
139 		B_AT_BI_KSTACK,
140 		B_AT_BI_USTACK,
141 		B_AT_BI_ARG0,
142 		B_AT_BI_ARG1,
143 		B_AT_BI_ARG2,
144 		B_AT_BI_ARG3,
145 		B_AT_BI_ARG4,
146 		B_AT_BI_ARG5,
147 		B_AT_BI_ARG6,
148 		B_AT_BI_ARG7,
149 		B_AT_BI_ARG8,
150 		B_AT_BI_ARG9,
151 		B_AT_BI_ARGS,
152 		B_AT_BI_RETVAL,
153 		B_AT_BI_PROBE,
154 
155 		B_AT_FN_STR,			/* str($1); str($1, 3); */
156 
157 		B_AT_MF_COUNT,			/* @map[key] = count() */
158 		B_AT_MF_MAX,			/* @map[key] = max(nsecs) */
159 		B_AT_MF_MIN,			/* @map[key] = min(pid) */
160 		B_AT_MF_SUM,			/* @map[key] = sum(@elapsed) */
161 
162 		B_AT_OP_PLUS,
163 		B_AT_OP_MINUS,
164 		B_AT_OP_MULT,
165 		B_AT_OP_DIVIDE,
166 		B_AT_OP_MODULO,
167 		B_AT_OP_BAND,
168 		B_AT_OP_XOR,
169 		B_AT_OP_BOR,
170 		B_AT_OP_EQ,
171 		B_AT_OP_NE,
172 		B_AT_OP_LE,
173 		B_AT_OP_LT,
174 		B_AT_OP_GE,
175 		B_AT_OP_GT,
176 		B_AT_OP_LAND,
177 		B_AT_OP_LOR,
178 	}			 ba_type;
179 };
180 
181 #define BA_INITIALIZER(v, t)	{ { NULL }, (void *)(v), NULL, (t) }
182 
183 /*
184  * Represents branches of an if-else statement.
185  */
186 struct bt_cond {
187 	struct bt_stmt		*bc_condbs;
188 	struct bt_stmt		*bc_elsebs;
189 };
190 
191 /*
192  * Each action associated with a given probe is made of at least one
193  * statement.
194  *
195  * Statements are interpreted linearly in userland to format data
196  * recorded in the form of events.
197  */
198 struct bt_stmt {
199 	SLIST_ENTRY(bt_stmt)	 bs_next;
200 	struct bt_var		*bs_var;	/* for STOREs */
201 	SLIST_HEAD(, bt_arg)	 bs_args;
202 	enum bt_action {
203 		B_AC_BUCKETIZE,			/* @h = hist(42) */
204 		B_AC_CLEAR,			/* clear(@map) */
205 		B_AC_DELETE,			/* delete(@map[key]) */
206 		B_AC_EXIT,			/* exit() */
207 		B_AC_INSERT,			/* @map[key] = 42 */
208 		B_AC_PRINT,			/* print(@map, 10) */
209 		B_AC_PRINTF,			/* printf("hello!\n") */
210 		B_AC_STORE,			/* @a = 3 */
211 		B_AC_TEST,			/* if (@a) */
212 		B_AC_TIME,			/* time("%H:%M:%S  ") */
213 		B_AC_ZERO,			/* zero(@map) */
214 	}			 bs_act;
215 };
216 
217 extern struct bt_ruleq	 g_rules;	/* Successfully parsed rules. */
218 extern int		 g_nprobes;	/* # of probes to attach */
219 extern struct bt_arg 	 g_nullba;
220 extern struct bt_arg	 g_maxba;
221 
222 int			 btparse(const char *, size_t, const char *, int);
223 
224 #define ba_new(v, t)	 ba_new0((void *)(v), (t))
225 struct bt_arg		*ba_new0(void *, enum bt_argtype);
226 
227 const char		*bv_name(struct bt_var *);
228 
229 #endif /* BT_PARSER_H */
230