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