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