/* Version for ABI between liblttng-ust, sessiond, consumerd */
#define LTTNG_UST_ABI_MAJOR_VERSION 7
-#define LTTNG_UST_ABI_MINOR_VERSION 1
+#define LTTNG_UST_ABI_MINOR_VERSION 2
enum lttng_ust_instrumentation {
LTTNG_UST_TRACEPOINT = 0,
} __attribute__((packed));
enum filter_op {
- FILTER_OP_UNKNOWN = 0,
+ FILTER_OP_UNKNOWN = 0,
- FILTER_OP_RETURN,
+ FILTER_OP_RETURN = 1,
/* binary */
- FILTER_OP_MUL,
- FILTER_OP_DIV,
- FILTER_OP_MOD,
- FILTER_OP_PLUS,
- FILTER_OP_MINUS,
- FILTER_OP_RSHIFT,
- FILTER_OP_LSHIFT,
- FILTER_OP_BIN_AND,
- FILTER_OP_BIN_OR,
- FILTER_OP_BIN_XOR,
+ FILTER_OP_MUL = 2,
+ FILTER_OP_DIV = 3,
+ FILTER_OP_MOD = 4,
+ FILTER_OP_PLUS = 5,
+ FILTER_OP_MINUS = 6,
+ FILTER_OP_RSHIFT = 7,
+ FILTER_OP_LSHIFT = 8,
+ FILTER_OP_BIN_AND = 9,
+ FILTER_OP_BIN_OR = 10,
+ FILTER_OP_BIN_XOR = 11,
/* binary comparators */
- FILTER_OP_EQ,
- FILTER_OP_NE,
- FILTER_OP_GT,
- FILTER_OP_LT,
- FILTER_OP_GE,
- FILTER_OP_LE,
-
- /* string binary comparator */
- FILTER_OP_EQ_STRING,
- FILTER_OP_NE_STRING,
- FILTER_OP_GT_STRING,
- FILTER_OP_LT_STRING,
- FILTER_OP_GE_STRING,
- FILTER_OP_LE_STRING,
+ FILTER_OP_EQ = 12,
+ FILTER_OP_NE = 13,
+ FILTER_OP_GT = 14,
+ FILTER_OP_LT = 15,
+ FILTER_OP_GE = 16,
+ FILTER_OP_LE = 17,
+
+ /* string binary comparator: apply to */
+ FILTER_OP_EQ_STRING = 18,
+ FILTER_OP_NE_STRING = 19,
+ FILTER_OP_GT_STRING = 20,
+ FILTER_OP_LT_STRING = 21,
+ FILTER_OP_GE_STRING = 22,
+ FILTER_OP_LE_STRING = 23,
/* s64 binary comparator */
- FILTER_OP_EQ_S64,
- FILTER_OP_NE_S64,
- FILTER_OP_GT_S64,
- FILTER_OP_LT_S64,
- FILTER_OP_GE_S64,
- FILTER_OP_LE_S64,
+ FILTER_OP_EQ_S64 = 24,
+ FILTER_OP_NE_S64 = 25,
+ FILTER_OP_GT_S64 = 26,
+ FILTER_OP_LT_S64 = 27,
+ FILTER_OP_GE_S64 = 28,
+ FILTER_OP_LE_S64 = 29,
/* double binary comparator */
- FILTER_OP_EQ_DOUBLE,
- FILTER_OP_NE_DOUBLE,
- FILTER_OP_GT_DOUBLE,
- FILTER_OP_LT_DOUBLE,
- FILTER_OP_GE_DOUBLE,
- FILTER_OP_LE_DOUBLE,
+ FILTER_OP_EQ_DOUBLE = 30,
+ FILTER_OP_NE_DOUBLE = 31,
+ FILTER_OP_GT_DOUBLE = 32,
+ FILTER_OP_LT_DOUBLE = 33,
+ FILTER_OP_GE_DOUBLE = 34,
+ FILTER_OP_LE_DOUBLE = 35,
/* Mixed S64-double binary comparators */
- FILTER_OP_EQ_DOUBLE_S64,
- FILTER_OP_NE_DOUBLE_S64,
- FILTER_OP_GT_DOUBLE_S64,
- FILTER_OP_LT_DOUBLE_S64,
- FILTER_OP_GE_DOUBLE_S64,
- FILTER_OP_LE_DOUBLE_S64,
-
- FILTER_OP_EQ_S64_DOUBLE,
- FILTER_OP_NE_S64_DOUBLE,
- FILTER_OP_GT_S64_DOUBLE,
- FILTER_OP_LT_S64_DOUBLE,
- FILTER_OP_GE_S64_DOUBLE,
- FILTER_OP_LE_S64_DOUBLE,
+ FILTER_OP_EQ_DOUBLE_S64 = 36,
+ FILTER_OP_NE_DOUBLE_S64 = 37,
+ FILTER_OP_GT_DOUBLE_S64 = 38,
+ FILTER_OP_LT_DOUBLE_S64 = 39,
+ FILTER_OP_GE_DOUBLE_S64 = 40,
+ FILTER_OP_LE_DOUBLE_S64 = 41,
+
+ FILTER_OP_EQ_S64_DOUBLE = 42,
+ FILTER_OP_NE_S64_DOUBLE = 43,
+ FILTER_OP_GT_S64_DOUBLE = 44,
+ FILTER_OP_LT_S64_DOUBLE = 45,
+ FILTER_OP_GE_S64_DOUBLE = 46,
+ FILTER_OP_LE_S64_DOUBLE = 47,
/* unary */
- FILTER_OP_UNARY_PLUS,
- FILTER_OP_UNARY_MINUS,
- FILTER_OP_UNARY_NOT,
- FILTER_OP_UNARY_PLUS_S64,
- FILTER_OP_UNARY_MINUS_S64,
- FILTER_OP_UNARY_NOT_S64,
- FILTER_OP_UNARY_PLUS_DOUBLE,
- FILTER_OP_UNARY_MINUS_DOUBLE,
- FILTER_OP_UNARY_NOT_DOUBLE,
+ FILTER_OP_UNARY_PLUS = 48,
+ FILTER_OP_UNARY_MINUS = 49,
+ FILTER_OP_UNARY_NOT = 50,
+ FILTER_OP_UNARY_PLUS_S64 = 51,
+ FILTER_OP_UNARY_MINUS_S64 = 52,
+ FILTER_OP_UNARY_NOT_S64 = 53,
+ FILTER_OP_UNARY_PLUS_DOUBLE = 54,
+ FILTER_OP_UNARY_MINUS_DOUBLE = 55,
+ FILTER_OP_UNARY_NOT_DOUBLE = 56,
/* logical */
- FILTER_OP_AND,
- FILTER_OP_OR,
+ FILTER_OP_AND = 57,
+ FILTER_OP_OR = 58,
/* load field ref */
- FILTER_OP_LOAD_FIELD_REF,
- FILTER_OP_LOAD_FIELD_REF_STRING,
- FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
- FILTER_OP_LOAD_FIELD_REF_S64,
- FILTER_OP_LOAD_FIELD_REF_DOUBLE,
+ FILTER_OP_LOAD_FIELD_REF = 59,
+ FILTER_OP_LOAD_FIELD_REF_STRING = 60,
+ FILTER_OP_LOAD_FIELD_REF_SEQUENCE = 61,
+ FILTER_OP_LOAD_FIELD_REF_S64 = 62,
+ FILTER_OP_LOAD_FIELD_REF_DOUBLE = 63,
/* load immediate from operand */
- FILTER_OP_LOAD_STRING,
- FILTER_OP_LOAD_S64,
- FILTER_OP_LOAD_DOUBLE,
+ FILTER_OP_LOAD_STRING = 64,
+ FILTER_OP_LOAD_S64 = 65,
+ FILTER_OP_LOAD_DOUBLE = 66,
/* cast */
- FILTER_OP_CAST_TO_S64,
- FILTER_OP_CAST_DOUBLE_TO_S64,
- FILTER_OP_CAST_NOP,
+ FILTER_OP_CAST_TO_S64 = 67,
+ FILTER_OP_CAST_DOUBLE_TO_S64 = 68,
+ FILTER_OP_CAST_NOP = 69,
/* get context ref */
- FILTER_OP_GET_CONTEXT_REF,
- FILTER_OP_GET_CONTEXT_REF_STRING,
- FILTER_OP_GET_CONTEXT_REF_S64,
- FILTER_OP_GET_CONTEXT_REF_DOUBLE,
+ FILTER_OP_GET_CONTEXT_REF = 70,
+ FILTER_OP_GET_CONTEXT_REF_STRING = 71,
+ FILTER_OP_GET_CONTEXT_REF_S64 = 72,
+ FILTER_OP_GET_CONTEXT_REF_DOUBLE = 73,
+
+ /* load userspace field ref */
+ FILTER_OP_LOAD_FIELD_REF_USER_STRING = 74,
+ FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE = 75,
+
+ /*
+ * load immediate star globbing pattern (literal string)
+ * from immediate
+ */
+ FILTER_OP_LOAD_STAR_GLOB_STRING = 76,
+
+ /* globbing pattern binary operator: apply to */
+ FILTER_OP_EQ_STAR_GLOB_STRING = 77,
+ FILTER_OP_NE_STAR_GLOB_STRING = 78,
NR_FILTER_OPS,
};
#define _LGPL_SOURCE
#include <urcu-pointer.h>
#include "lttng-filter.h"
+#include "string-utils.h"
/*
* -1: wildcard found.
}
}
+/*
+ * Returns -1ULL if the string is null-terminated, or the number of
+ * characters if not.
+ */
+static
+size_t get_str_or_seq_len(const struct estack_entry *entry)
+{
+ if (entry->u.s.seq_len == UINT_MAX) {
+ return -1ULL;
+ } else {
+ return entry->u.s.seq_len;
+ }
+}
+
+static
+int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
+{
+ const char *pattern;
+ const char *candidate;
+ size_t pattern_len;
+ size_t candidate_len;
+
+ /* Find out which side is the pattern vs. the candidate. */
+ if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
+ pattern = estack_ax(stack, top)->u.s.str;
+ pattern_len = get_str_or_seq_len(estack_ax(stack, top));
+ candidate = estack_bx(stack, top)->u.s.str;
+ candidate_len = get_str_or_seq_len(estack_bx(stack, top));
+ } else {
+ pattern = estack_bx(stack, top)->u.s.str;
+ pattern_len = get_str_or_seq_len(estack_bx(stack, top));
+ candidate = estack_ax(stack, top)->u.s.str;
+ candidate_len = get_str_or_seq_len(estack_ax(stack, top));
+ }
+
+ /* Perform the match. Returns 0 when the result is true. */
+ return !strutils_star_glob_match(pattern, pattern_len, candidate,
+ candidate_len);
+}
+
static
int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
{
if (q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0') {
return 0;
} else {
- if (estack_ax(stack, top)->u.s.literal) {
+ if (estack_ax(stack, top)->u.s.literal_type ==
+ ESTACK_STRING_LITERAL_TYPE_PLAIN) {
ret = parse_char(&q);
if (ret == -1)
return 0;
}
}
if (unlikely(q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0')) {
- if (estack_bx(stack, top)->u.s.literal) {
+ if (estack_bx(stack, top)->u.s.literal_type ==
+ ESTACK_STRING_LITERAL_TYPE_PLAIN) {
ret = parse_char(&p);
if (ret == -1)
return 0;
}
return 1;
}
- if (estack_bx(stack, top)->u.s.literal) {
+ if (estack_bx(stack, top)->u.s.literal_type ==
+ ESTACK_STRING_LITERAL_TYPE_PLAIN) {
ret = parse_char(&p);
if (ret == -1) {
return 0;
}
/* else compare both char */
}
- if (estack_ax(stack, top)->u.s.literal) {
+ if (estack_ax(stack, top)->u.s.literal_type ==
+ ESTACK_STRING_LITERAL_TYPE_PLAIN) {
ret = parse_char(&q);
if (ret == -1) {
return 0;
[ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
[ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
+ /* globbing pattern binary comparator */
+ [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
+ [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
+
/* s64 binary comparator */
[ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
[ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
/* load from immediate operand */
[ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
+ [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
[ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
[ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
JUMP_TO(FILTER_OP_EQ_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_EQ_DOUBLE_S64);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_EQ_S64_DOUBLE);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_EQ_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
goto end;
case REG_STRING:
JUMP_TO(FILTER_OP_EQ_STRING);
+ case REG_STAR_GLOB_STRING:
+ JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
+ default:
+ ERR("Unknown filter register type (%d)",
+ (int) estack_bx_t);
+ ret = -EINVAL;
+ goto end;
+ }
+ break;
+ case REG_STAR_GLOB_STRING:
+ switch (estack_bx_t) {
+ case REG_S64: /* Fall-through */
+ case REG_DOUBLE:
+ ret = -EINVAL;
+ goto end;
+ case REG_STRING:
+ JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
+ case REG_STAR_GLOB_STRING:
+ ret = -EINVAL;
+ goto end;
default:
ERR("Unknown filter register type (%d)",
(int) estack_bx_t);
JUMP_TO(FILTER_OP_NE_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_NE_DOUBLE_S64);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_NE_S64_DOUBLE);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_NE_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
goto end;
case REG_STRING:
JUMP_TO(FILTER_OP_NE_STRING);
+ case REG_STAR_GLOB_STRING:
+ JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
+ default:
+ ERR("Unknown filter register type (%d)",
+ (int) estack_bx_t);
+ ret = -EINVAL;
+ goto end;
+ }
+ break;
+ case REG_STAR_GLOB_STRING:
+ switch (estack_bx_t) {
+ case REG_S64: /* Fall-through */
+ case REG_DOUBLE:
+ ret = -EINVAL;
+ goto end;
+ case REG_STRING:
+ JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
+ case REG_STAR_GLOB_STRING:
+ ret = -EINVAL;
+ goto end;
default:
ERR("Unknown filter register type (%d)",
(int) estack_bx_t);
JUMP_TO(FILTER_OP_GT_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_GT_DOUBLE_S64);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_GT_S64_DOUBLE);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_GT_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
case REG_STRING:
switch (estack_bx_t) {
case REG_S64: /* Fall-through */
- case REG_DOUBLE:
+ case REG_DOUBLE: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
case REG_STRING:
JUMP_TO(FILTER_OP_LT_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_LT_DOUBLE_S64);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_LT_S64_DOUBLE);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_LT_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
case REG_STRING:
switch (estack_bx_t) {
case REG_S64: /* Fall-through */
- case REG_DOUBLE:
+ case REG_DOUBLE: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
case REG_STRING:
JUMP_TO(FILTER_OP_GE_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_GE_DOUBLE_S64);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_GE_S64_DOUBLE);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_GE_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
case REG_STRING:
switch (estack_bx_t) {
case REG_S64: /* Fall-through */
- case REG_DOUBLE:
+ case REG_DOUBLE: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
case REG_STRING:
JUMP_TO(FILTER_OP_LE_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_LE_DOUBLE_S64);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_LE_S64_DOUBLE);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_LE_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
case REG_STRING:
switch (estack_bx_t) {
case REG_S64: /* Fall-through */
- case REG_DOUBLE:
+ case REG_DOUBLE: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
case REG_STRING:
PO;
}
+ OP(FILTER_OP_EQ_STAR_GLOB_STRING):
+ {
+ int res;
+
+ res = (stack_star_glob_match(stack, top, "==") == 0);
+ estack_pop(stack, top, ax, bx, ax_t, bx_t);
+ estack_ax_v = res;
+ estack_ax_t = REG_S64;
+ next_pc += sizeof(struct binary_op);
+ PO;
+ }
+ OP(FILTER_OP_NE_STAR_GLOB_STRING):
+ {
+ int res;
+
+ res = (stack_star_glob_match(stack, top, "!=") != 0);
+ estack_pop(stack, top, ax, bx, ax_t, bx_t);
+ estack_ax_v = res;
+ estack_ax_t = REG_S64;
+ next_pc += sizeof(struct binary_op);
+ PO;
+ }
+
OP(FILTER_OP_EQ_S64):
{
int res;
JUMP_TO(FILTER_OP_UNARY_PLUS_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_UNARY_MINUS_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
JUMP_TO(FILTER_OP_UNARY_NOT_S64);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
goto end;
}
estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
- estack_ax(stack, top)->u.s.literal = 0;
+ estack_ax(stack, top)->u.s.literal_type =
+ ESTACK_STRING_LITERAL_TYPE_NONE;
estack_ax_t = REG_STRING;
dbg_printf("ref load string %s\n", estack_ax(stack, top)->u.s.str);
next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
ret = -EINVAL;
goto end;
}
- estack_ax(stack, top)->u.s.literal = 0;
+ estack_ax(stack, top)->u.s.literal_type =
+ ESTACK_STRING_LITERAL_TYPE_NONE;
next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
PO;
}
estack_push(stack, top, ax, bx, ax_t, bx_t);
estack_ax(stack, top)->u.s.str = insn->data;
estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
- estack_ax(stack, top)->u.s.literal = 1;
+ estack_ax(stack, top)->u.s.literal_type =
+ ESTACK_STRING_LITERAL_TYPE_PLAIN;
estack_ax_t = REG_STRING;
next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
PO;
}
+ OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
+ {
+ struct load_op *insn = (struct load_op *) pc;
+
+ dbg_printf("load globbing pattern %s\n", insn->data);
+ estack_push(stack, top, ax, bx, ax_t, bx_t);
+ estack_ax(stack, top)->u.s.str = insn->data;
+ estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
+ estack_ax(stack, top)->u.s.literal_type =
+ ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
+ estack_ax_t = REG_STAR_GLOB_STRING;
+ next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
+ PO;
+ }
+
OP(FILTER_OP_LOAD_S64):
{
struct load_op *insn = (struct load_op *) pc;
JUMP_TO(FILTER_OP_CAST_NOP);
case REG_DOUBLE:
JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64);
- case REG_STRING:
+ case REG_STRING: /* Fall-through */
+ case REG_STAR_GLOB_STRING:
ret = -EINVAL;
goto end;
default:
goto end;
}
estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
- estack_ax(stack, top)->u.s.literal = 0;
+ estack_ax(stack, top)->u.s.literal_type =
+ ESTACK_STRING_LITERAL_TYPE_NONE;
dbg_printf("ref get context dynamic string %s\n", estack_ax(stack, top)->u.s.str);
estack_ax_t = REG_STRING;
break;
goto end;
}
estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
- estack_ax(stack, top)->u.s.literal = 0;
+ estack_ax(stack, top)->u.s.literal_type =
+ ESTACK_STRING_LITERAL_TYPE_NONE;
estack_ax_t = REG_STRING;
dbg_printf("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
case REG_STRING:
if (vstack_bx(stack)->type == REG_UNKNOWN)
break;
- insn->op = FILTER_OP_EQ_STRING;
+ if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING)
+ insn->op = FILTER_OP_EQ_STAR_GLOB_STRING;
+ else
+ insn->op = FILTER_OP_EQ_STRING;
+ break;
+ case REG_STAR_GLOB_STRING:
+ if (vstack_bx(stack)->type == REG_UNKNOWN)
+ break;
+ insn->op = FILTER_OP_EQ_STAR_GLOB_STRING;
break;
case REG_S64:
if (vstack_bx(stack)->type == REG_UNKNOWN)
case REG_STRING:
if (vstack_bx(stack)->type == REG_UNKNOWN)
break;
- insn->op = FILTER_OP_NE_STRING;
+ if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING)
+ insn->op = FILTER_OP_NE_STAR_GLOB_STRING;
+ else
+ insn->op = FILTER_OP_NE_STRING;
+ break;
+ case REG_STAR_GLOB_STRING:
+ if (vstack_bx(stack)->type == REG_UNKNOWN)
+ break;
+ insn->op = FILTER_OP_NE_STAR_GLOB_STRING;
break;
case REG_S64:
if (vstack_bx(stack)->type == REG_UNKNOWN)
ret = -EINVAL;
goto end;
+ case REG_STAR_GLOB_STRING:
+ ERR("invalid register type for > binary operator\n");
+ ret = -EINVAL;
+ goto end;
case REG_STRING:
if (vstack_bx(stack)->type == REG_UNKNOWN)
break;
ret = -EINVAL;
goto end;
+ case REG_STAR_GLOB_STRING:
+ ERR("invalid register type for < binary operator\n");
+ ret = -EINVAL;
+ goto end;
case REG_STRING:
if (vstack_bx(stack)->type == REG_UNKNOWN)
break;
ret = -EINVAL;
goto end;
+ case REG_STAR_GLOB_STRING:
+ ERR("invalid register type for >= binary operator\n");
+ ret = -EINVAL;
+ goto end;
case REG_STRING:
if (vstack_bx(stack)->type == REG_UNKNOWN)
break;
ret = -EINVAL;
goto end;
+ case REG_STAR_GLOB_STRING:
+ ERR("invalid register type for <= binary operator\n");
+ ret = -EINVAL;
+ goto end;
case REG_STRING:
if (vstack_bx(stack)->type == REG_UNKNOWN)
break;
case FILTER_OP_LT_STRING:
case FILTER_OP_GE_STRING:
case FILTER_OP_LE_STRING:
+ case FILTER_OP_EQ_STAR_GLOB_STRING:
+ case FILTER_OP_NE_STAR_GLOB_STRING:
case FILTER_OP_EQ_S64:
case FILTER_OP_NE_S64:
case FILTER_OP_GT_S64:
break;
}
+ case FILTER_OP_LOAD_STAR_GLOB_STRING:
+ {
+ struct load_op *insn = (struct load_op *) pc;
+
+ if (vstack_push(stack)) {
+ ret = -EINVAL;
+ goto end;
+ }
+ vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
+ next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
+ break;
+ }
+
case FILTER_OP_LOAD_S64:
{
if (vstack_push(stack)) {
goto end;
case REG_STRING:
+ case REG_STAR_GLOB_STRING:
ERR("Cast op can only be applied to numeric or floating point registers\n");
ret = -EINVAL;
goto end;
#include <urcu/rculfhash.h>
#include "lttng-hash-helper.h"
+#include "string-utils.h"
/*
* Number of merge points for hash table size. Hash table initialized to
* (unknown), negative error value on error.
*/
static
-int bin_op_compare_check(struct vstack *stack, const char *str)
+int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode,
+ const char *str)
{
if (unlikely(!vstack_ax(stack) || !vstack_bx(stack)))
goto error_empty;
goto unknown;
case REG_STRING:
break;
+ case REG_STAR_GLOB_STRING:
+ if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
+ goto error_mismatch;
+ }
+ break;
+ case REG_S64:
+ case REG_DOUBLE:
+ goto error_mismatch;
+ }
+ break;
+ case REG_STAR_GLOB_STRING:
+ switch (vstack_bx(stack)->type) {
+ default:
+ goto error_type;
+
+ case REG_UNKNOWN:
+ goto unknown;
+ case REG_STRING:
+ if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
+ goto error_mismatch;
+ }
+ break;
+ case REG_STAR_GLOB_STRING:
case REG_S64:
case REG_DOUBLE:
goto error_mismatch;
case REG_UNKNOWN:
goto unknown;
case REG_STRING:
+ case REG_STAR_GLOB_STRING:
goto error_mismatch;
case REG_S64:
case REG_DOUBLE:
case FILTER_OP_LT_STRING:
case FILTER_OP_GE_STRING:
case FILTER_OP_LE_STRING:
+ case FILTER_OP_EQ_STAR_GLOB_STRING:
+ case FILTER_OP_NE_STAR_GLOB_STRING:
case FILTER_OP_EQ_S64:
case FILTER_OP_NE_S64:
case FILTER_OP_GT_S64:
/* load from immediate operand */
case FILTER_OP_LOAD_STRING:
+ case FILTER_OP_LOAD_STAR_GLOB_STRING:
{
struct load_op *insn = (struct load_op *) pc;
uint32_t str_len, maxlen;
char *pc)
{
int ret = 0;
+ const filter_opcode_t opcode = *(filter_opcode_t *) pc;
- switch (*(filter_opcode_t *) pc) {
+ switch (opcode) {
case FILTER_OP_UNKNOWN:
default:
{
case FILTER_OP_BIN_XOR:
{
ERR("unsupported bytecode op %u\n",
- (unsigned int) *(filter_opcode_t *) pc);
+ (unsigned int) opcode);
ret = -EINVAL;
goto end;
}
case FILTER_OP_EQ:
{
- ret = bin_op_compare_check(stack, "==");
+ ret = bin_op_compare_check(stack, opcode, "==");
if (ret < 0)
goto end;
break;
}
case FILTER_OP_NE:
{
- ret = bin_op_compare_check(stack, "!=");
+ ret = bin_op_compare_check(stack, opcode, "!=");
if (ret < 0)
goto end;
break;
}
case FILTER_OP_GT:
{
- ret = bin_op_compare_check(stack, ">");
+ ret = bin_op_compare_check(stack, opcode, ">");
if (ret < 0)
goto end;
break;
}
case FILTER_OP_LT:
{
- ret = bin_op_compare_check(stack, "<");
+ ret = bin_op_compare_check(stack, opcode, "<");
if (ret < 0)
goto end;
break;
}
case FILTER_OP_GE:
{
- ret = bin_op_compare_check(stack, ">=");
+ ret = bin_op_compare_check(stack, opcode, ">=");
if (ret < 0)
goto end;
break;
}
case FILTER_OP_LE:
{
- ret = bin_op_compare_check(stack, "<=");
+ ret = bin_op_compare_check(stack, opcode, "<=");
if (ret < 0)
goto end;
break;
break;
}
+ case FILTER_OP_EQ_STAR_GLOB_STRING:
+ case FILTER_OP_NE_STAR_GLOB_STRING:
+ {
+ if (!vstack_ax(stack) || !vstack_bx(stack)) {
+ ERR("Empty stack\n");
+ ret = -EINVAL;
+ goto end;
+ }
+ if (vstack_ax(stack)->type != REG_STAR_GLOB_STRING
+ && vstack_bx(stack)->type != REG_STAR_GLOB_STRING) {
+ ERR("Unexpected register type for globbing pattern comparator\n");
+ ret = -EINVAL;
+ goto end;
+ }
+ break;
+ }
+
case FILTER_OP_EQ_S64:
case FILTER_OP_NE_S64:
case FILTER_OP_GT_S64:
goto end;
case REG_STRING:
+ case REG_STAR_GLOB_STRING:
ERR("Unary op can only be applied to numeric or floating point registers\n");
ret = -EINVAL;
goto end;
/* load from immediate operand */
case FILTER_OP_LOAD_STRING:
+ case FILTER_OP_LOAD_STAR_GLOB_STRING:
{
break;
}
goto end;
case REG_STRING:
+ case REG_STAR_GLOB_STRING:
ERR("Cast op can only be applied to numeric or floating point registers\n");
ret = -EINVAL;
goto end;
node = cds_lfht_iter_get_node(&iter);
if (node) {
mp_node = caa_container_of(node, struct lfht_mp_node, node);
-
+
dbg_printf("Filter: validate merge point at offset %lu\n",
target_pc);
if (merge_points_compare(stack, &mp_node->stack)) {
case FILTER_OP_LT_STRING:
case FILTER_OP_GE_STRING:
case FILTER_OP_LE_STRING:
+ case FILTER_OP_EQ_STAR_GLOB_STRING:
+ case FILTER_OP_NE_STAR_GLOB_STRING:
case FILTER_OP_EQ_S64:
case FILTER_OP_NE_S64:
case FILTER_OP_GT_S64:
break;
}
+ case FILTER_OP_LOAD_STAR_GLOB_STRING:
+ {
+ struct load_op *insn = (struct load_op *) pc;
+
+ if (vstack_push(stack)) {
+ ret = -EINVAL;
+ goto end;
+ }
+ vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
+ next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
+ break;
+ }
+
case FILTER_OP_LOAD_S64:
{
if (vstack_push(stack)) {
REG_S64,
REG_DOUBLE,
REG_STRING,
+ REG_STAR_GLOB_STRING,
REG_UNKNOWN,
};
}
/* Execution stack */
+enum estack_string_literal_type {
+ ESTACK_STRING_LITERAL_TYPE_NONE,
+ ESTACK_STRING_LITERAL_TYPE_PLAIN,
+ ESTACK_STRING_LITERAL_TYPE_STAR_GLOB,
+};
+
struct estack_entry {
enum entry_type type; /* For dynamic typing. */
union {
struct {
const char *str;
size_t seq_len;
- int literal; /* is string literal ? */
+ enum estack_string_literal_type literal_type;
} s;
} u;
};