xref: /openbsd-src/usr.sbin/btrace/bt_parser.h (revision de8cc8edbc71bd3e3bc7fbffa27ba0e564c37d8b)
1 /*	$OpenBSD: bt_parser.h,v 1.13 2021/02/08 09:46:45 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:rate"
35  */
36 struct bt_probe {
37 	const char		*bp_prov;	/* provider */
38 	const char		*bp_func;	/* function or time unit */
39 	const char		*bp_name;
40 	uint32_t		 bp_rate;
41 #define bp_unit	bp_func
42 };
43 
44 
45 /*
46  * Event filters correspond to checks performed in-kernel.
47  */
48 struct bt_evtfilter {
49 	int			bf_op;
50 	enum bt_filtervar {
51 		B_FV_NONE = 1,
52 		B_FV_PID,
53 		B_FV_TID
54 	}			 bf_var;
55 	uint32_t		 bf_val;
56 };
57 
58 /*
59  * Filters, also known as predicates, describe under which set of
60  * conditions a rule is executed.
61  *
62  * Depending on their type they are performed in-kernel or when a rule
63  * is evaluated.  In the first case they might prevent the recording of
64  * events, in the second case events might be discarded at runtime.
65  */
66 struct bt_filter {
67 	struct bt_evtfilter	  bf_evtfilter;	/* in-kernel event filter */
68 	struct bt_stmt		 *bf_condition;	/* per event condition */
69 };
70 
71 TAILQ_HEAD(bt_ruleq, bt_rule);
72 
73 /*
74  * A rule is the language representation of which 'action' to attach to
75  * which 'probe' under which conditions ('filter').  In other words it
76  * represents the following:
77  *
78  *	probe / filter / { action }
79  */
80 struct bt_rule {
81 	TAILQ_ENTRY(bt_rule)	 br_next;	/* linkage in global list */
82 	struct bt_probe		*br_probe;
83 	struct bt_filter	*br_filter;
84 	SLIST_HEAD(, bt_stmt)	 br_action;
85 
86 	enum bt_rtype {
87 		 B_RT_BEGIN = 1,
88 		 B_RT_END,
89 		 B_RT_PROBE,
90 	}			 br_type;	/* BEGIN, END or 'probe' */
91 
92 	uint32_t		 br_pbn;	/* ID assigned by the kernel */
93 	void			*br_cookie;
94 };
95 
96 /*
97  * Global 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 };
106 
107 /*
108  * Respresentation of an argument.
109  *
110  * A so called "argument" can be any symbol representing a value or
111  * a combination of those through an operation.
112  */
113 struct bt_arg {
114 	SLIST_ENTRY(bt_arg)	 ba_next;
115 	void			*ba_value;
116 	struct bt_arg		*ba_key;	/* key for maps/histograms */
117 	enum  bt_argtype {
118 		B_AT_STR = 1,			/* C-style string */
119 		B_AT_LONG,			/* Number (integer) */
120 		B_AT_VAR,			/* global variable (@var) */
121 		B_AT_MAP,			/* global map (@map[]) */
122 		B_AT_HIST,			/* histogram */
123 
124 		B_AT_BI_PID,
125 		B_AT_BI_TID,
126 		B_AT_BI_COMM,
127 		B_AT_BI_CPU,
128 		B_AT_BI_NSECS,
129 		B_AT_BI_KSTACK,
130 		B_AT_BI_USTACK,
131 		B_AT_BI_ARG0,
132 		B_AT_BI_ARG1,
133 		B_AT_BI_ARG2,
134 		B_AT_BI_ARG3,
135 		B_AT_BI_ARG4,
136 		B_AT_BI_ARG5,
137 		B_AT_BI_ARG6,
138 		B_AT_BI_ARG7,
139 		B_AT_BI_ARG8,
140 		B_AT_BI_ARG9,
141 		B_AT_BI_ARGS,
142 		B_AT_BI_RETVAL,
143 
144 		B_AT_MF_COUNT,			/* @map[key] = count() */
145 		B_AT_MF_MAX,			/* @map[key] = max(nsecs) */
146 		B_AT_MF_MIN,			/* @map[key] = min(pid) */
147 		B_AT_MF_SUM,			/* @map[key] = sum(@elapsed) */
148 
149 		B_AT_OP_PLUS,
150 		B_AT_OP_MINUS,
151 		B_AT_OP_MULT,
152 		B_AT_OP_DIVIDE,
153 		B_AT_OP_BAND,
154 		B_AT_OP_BOR,
155 		B_AT_OP_EQ,
156 		B_AT_OP_NE,
157 		B_AT_OP_LE,
158 		B_AT_OP_GE,
159 		B_AT_OP_LAND,
160 		B_AT_OP_LOR,
161 	}			 ba_type;
162 };
163 
164 #define BA_INITIALIZER(v, t)	{ { NULL }, (void *)(v), NULL, (t) }
165 
166 /*
167  * Each action associated with a given probe is made of at least one
168  * statement.
169  *
170  * Statements are interpreted linearly in userland to format data
171  * recorded in the form of events.
172  */
173 struct bt_stmt {
174 	SLIST_ENTRY(bt_stmt)	 bs_next;
175 	struct bt_var		*bs_var;	/* for STOREs */
176 	SLIST_HEAD(, bt_arg)	 bs_args;
177 	enum bt_action {
178 		B_AC_BUCKETIZE,			/* @h = hist(42) */
179 		B_AC_CLEAR,			/* clear(@map) */
180 		B_AC_DELETE,			/* delete(@map[key]) */
181 		B_AC_EXIT,			/* exit() */
182 		B_AC_INSERT,			/* @map[key] = 42 */
183 		B_AC_PRINT,			/* print(@map, 10) */
184 		B_AC_PRINTF,			/* printf("hello!\n") */
185 		B_AC_STORE,			/* @a = 3 */
186 		B_AC_TEST,			/* if (@a) */
187 		B_AC_TIME,			/* time("%H:%M:%S  ") */
188 		B_AC_ZERO,			/* zero(@map) */
189 	}			 bs_act;
190 };
191 
192 extern struct bt_ruleq	 g_rules;	/* Successfully parsed rules. */
193 extern int		 g_nprobes;	/* # of probes to attach */
194 
195 int			 btparse(const char *, size_t, const char *, int);
196 
197 #define ba_new(v, t)	 ba_new0((void *)(v), (t))
198 struct bt_arg		*ba_new0(void *, enum bt_argtype);
199 
200 const char		*bv_name(struct bt_var *);
201 
202 void			 bm_insert(struct bt_var *, struct bt_arg *,
203 			     struct bt_arg *);
204 
205 #endif /* BT_PARSER_H */
206