-/* $OpenBSD: btrace.c,v 1.66 2022/11/11 22:43:09 mpi Exp $ */
+/* $OpenBSD: btrace.c,v 1.67 2022/11/12 14:19:08 mpi Exp $ */
/*
* Copyright (c) 2019 - 2021 Martin Pieuchot <mpi@openbsd.org>
struct bt_rule *r, *rbegin = NULL;
struct bt_probe *bp;
struct bt_stmt *bs;
+ struct bt_arg *ba;
int dokstack = 0, on = 1;
uint64_t evtflags;
TAILQ_FOREACH(r, &g_rules, br_next) {
evtflags = 0;
- SLIST_FOREACH(bs, &r->br_action, bs_next) {
- struct bt_arg *ba;
+ if (r->br_filter != NULL &&
+ r->br_filter->bf_condition != NULL) {
+
+ bs = r->br_filter->bf_condition;
+ ba = SLIST_FIRST(&bs->bs_args);
+
+ evtflags |= ba2dtflags(ba);
+ }
+
+ SLIST_FOREACH(bs, &r->br_action, bs_next) {
SLIST_FOREACH(ba, &bs->bs_args, ba_next)
evtflags |= ba2dtflags(ba);
lhs = ba->ba_value;
rhs = SLIST_NEXT(lhs, ba_next);
+ /*
+ * String comparison also use '==' and '!='.
+ */
+ if (lhs->ba_type == B_AT_STR ||
+ (rhs != NULL && rhs->ba_type == B_AT_STR)) {
+ char lstr[STRLEN], rstr[STRLEN];
+
+ strlcpy(lstr, ba2str(lhs, dtev), sizeof(lstr));
+ strlcpy(rstr, ba2str(rhs, dtev), sizeof(rstr));
+
+ result = strncmp(lstr, rstr, STRLEN) == 0;
+
+ switch (ba->ba_type) {
+ case B_AT_OP_EQ:
+ break;
+ case B_AT_OP_NE:
+ result = !result;
+ break;
+ default:
+ warnx("operation '%d' unsupported on strings",
+ ba->ba_type);
+ result = 1;
+ }
+
+ debug("ba=%p eval '(%s %s %s) = %d'\n", ba, lstr, ba_name(ba),
+ rstr, result);
+
+ goto out;
+ }
+
lval = ba2long(lhs, dtev);
if (rhs == NULL) {
rval = 0;
xabort("unsupported operation %d", ba->ba_type);
}
- debug("ba=%p eval '%ld %s %ld = %d'\n", ba, lval, ba_name(ba),
+ debug("ba=%p eval '(%ld %s %ld) = %d'\n", ba, lval, ba_name(ba),
rval, result);
+out:
--recursions;
return result;
ba_name(struct bt_arg *ba)
{
switch (ba->ba_type) {
+ case B_AT_STR:
+ return (const char *)ba->ba_value;
+ case B_AT_LONG:
+ return ba2str(ba, NULL);
case B_AT_NIL:
return "0";
case B_AT_VAR:
case B_AT_MAP:
+ case B_AT_HIST:
break;
case B_AT_BI_PID:
return "pid";
xabort("unsupported type %d", ba->ba_type);
}
- assert(ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP);
+ assert(ba->ba_type == B_AT_VAR || ba->ba_type == B_AT_MAP ||
+ ba->ba_type == B_AT_HIST);
static char buf[64];
size_t sz;
int
ba2dtflags(struct bt_arg *ba)
{
+ static long recursions;
struct bt_arg *bval;
int flags = 0;
+ if (++recursions >= __MAXOPERANDS)
+ errx(1, "too many operands (>%d) in expression", __MAXOPERANDS);
+
do {
if (ba->ba_type == B_AT_MAP)
bval = ba->ba_key;
case B_AT_MF_MIN:
case B_AT_MF_SUM:
case B_AT_FN_STR:
+ break;
case B_AT_OP_PLUS ... B_AT_OP_LOR:
+ flags |= ba2dtflags(bval->ba_value);
break;
default:
xabort("invalid argument type %d", bval->ba_type);
}
} while ((ba = SLIST_NEXT(ba, ba_next)) != NULL);
+ --recursions;
+
return flags;
}