afea3f151ff460e5dda5f5beef2908340ab10671
[lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
1 /*
2 * lttng-filter-interpreter.c
3 *
4 * LTTng UST filter interpreter.
5 *
6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27 #define _LGPL_SOURCE
28 #include <urcu-pointer.h>
29 #include "lttng-filter.h"
30 #include "string-utils.h"
31
32 /*
33 * -1: wildcard found.
34 * -2: unknown escape char.
35 * 0: normal char.
36 */
37
38 static
39 int parse_char(const char **p)
40 {
41 switch (**p) {
42 case '\\':
43 (*p)++;
44 switch (**p) {
45 case '\\':
46 case '*':
47 return 0;
48 default:
49 return -2;
50 }
51 case '*':
52 return -1;
53 default:
54 return 0;
55 }
56 }
57
58 /*
59 * Returns -1ULL if the string is null-terminated, or the number of
60 * characters if not.
61 */
62 static
63 size_t get_str_or_seq_len(const struct estack_entry *entry)
64 {
65 if (entry->u.s.seq_len == UINT_MAX) {
66 return -1ULL;
67 } else {
68 return entry->u.s.seq_len;
69 }
70 }
71
72 static
73 int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
74 {
75 const char *pattern;
76 const char *candidate;
77 size_t pattern_len;
78 size_t candidate_len;
79
80 /* Find out which side is the pattern vs. the candidate. */
81 if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
82 pattern = estack_ax(stack, top)->u.s.str;
83 pattern_len = get_str_or_seq_len(estack_ax(stack, top));
84 candidate = estack_bx(stack, top)->u.s.str;
85 candidate_len = get_str_or_seq_len(estack_bx(stack, top));
86 } else {
87 pattern = estack_bx(stack, top)->u.s.str;
88 pattern_len = get_str_or_seq_len(estack_bx(stack, top));
89 candidate = estack_ax(stack, top)->u.s.str;
90 candidate_len = get_str_or_seq_len(estack_ax(stack, top));
91 }
92
93 /* Perform the match. Returns 0 when the result is true. */
94 return !strutils_star_glob_match(pattern, pattern_len, candidate,
95 candidate_len);
96 }
97
98 static
99 int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
100 {
101 const char *p = estack_bx(stack, top)->u.s.str, *q = estack_ax(stack, top)->u.s.str;
102 int ret;
103 int diff;
104
105 for (;;) {
106 int escaped_r0 = 0;
107
108 if (unlikely(p - estack_bx(stack, top)->u.s.str >= estack_bx(stack, top)->u.s.seq_len || *p == '\0')) {
109 if (q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0') {
110 return 0;
111 } else {
112 if (estack_ax(stack, top)->u.s.literal_type ==
113 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
114 ret = parse_char(&q);
115 if (ret == -1)
116 return 0;
117 }
118 return -1;
119 }
120 }
121 if (unlikely(q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0')) {
122 if (estack_bx(stack, top)->u.s.literal_type ==
123 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
124 ret = parse_char(&p);
125 if (ret == -1)
126 return 0;
127 }
128 return 1;
129 }
130 if (estack_bx(stack, top)->u.s.literal_type ==
131 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
132 ret = parse_char(&p);
133 if (ret == -1) {
134 return 0;
135 } else if (ret == -2) {
136 escaped_r0 = 1;
137 }
138 /* else compare both char */
139 }
140 if (estack_ax(stack, top)->u.s.literal_type ==
141 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
142 ret = parse_char(&q);
143 if (ret == -1) {
144 return 0;
145 } else if (ret == -2) {
146 if (!escaped_r0)
147 return -1;
148 } else {
149 if (escaped_r0)
150 return 1;
151 }
152 } else {
153 if (escaped_r0)
154 return 1;
155 }
156 diff = *p - *q;
157 if (diff != 0)
158 break;
159 p++;
160 q++;
161 }
162 return diff;
163 }
164
165 uint64_t lttng_filter_false(void *filter_data,
166 const char *filter_stack_data)
167 {
168 return 0;
169 }
170
171 #ifdef INTERPRETER_USE_SWITCH
172
173 /*
174 * Fallback for compilers that do not support taking address of labels.
175 */
176
177 #define START_OP \
178 start_pc = &bytecode->data[0]; \
179 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
180 pc = next_pc) { \
181 dbg_printf("Executing op %s (%u)\n", \
182 print_op((unsigned int) *(filter_opcode_t *) pc), \
183 (unsigned int) *(filter_opcode_t *) pc); \
184 switch (*(filter_opcode_t *) pc) {
185
186 #define OP(name) jump_target_##name: __attribute__((unused)); \
187 case name
188
189 #define PO break
190
191 #define END_OP } \
192 }
193
194 #define JUMP_TO(name) \
195 goto jump_target_##name
196
197 #else
198
199 /*
200 * Dispatch-table based interpreter.
201 */
202
203 #define START_OP \
204 start_pc = &bytecode->data[0]; \
205 pc = next_pc = start_pc; \
206 if (unlikely(pc - start_pc >= bytecode->len)) \
207 goto end; \
208 goto *dispatch[*(filter_opcode_t *) pc];
209
210 #define OP(name) \
211 LABEL_##name
212
213 #define PO \
214 pc = next_pc; \
215 goto *dispatch[*(filter_opcode_t *) pc];
216
217 #define END_OP
218
219 #define JUMP_TO(name) \
220 goto LABEL_##name
221
222 #endif
223
224 /*
225 * Return 0 (discard), or raise the 0x1 flag (log event).
226 * Currently, other flags are kept for future extensions and have no
227 * effect.
228 */
229 uint64_t lttng_filter_interpret_bytecode(void *filter_data,
230 const char *filter_stack_data)
231 {
232 struct bytecode_runtime *bytecode = filter_data;
233 struct lttng_session *session = bytecode->p.session;
234 void *pc, *next_pc, *start_pc;
235 int ret = -EINVAL;
236 uint64_t retval = 0;
237 struct estack _stack;
238 struct estack *stack = &_stack;
239 register int64_t ax = 0, bx = 0;
240 register enum entry_type ax_t = REG_UNKNOWN, bx_t = REG_UNKNOWN;
241 register int top = FILTER_STACK_EMPTY;
242 #ifndef INTERPRETER_USE_SWITCH
243 static void *dispatch[NR_FILTER_OPS] = {
244 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
245
246 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
247
248 /* binary */
249 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
250 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
251 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
252 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
253 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
254 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
255 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
256 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
257 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
258 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
259
260 /* binary comparators */
261 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
262 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
263 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
264 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
265 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
266 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
267
268 /* string binary comparator */
269 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
270 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
271 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
272 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
273 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
274 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
275
276 /* globbing pattern binary comparator */
277 [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
278 [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
279
280 /* s64 binary comparator */
281 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
282 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
283 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
284 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
285 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
286 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
287
288 /* double binary comparator */
289 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
290 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
291 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
292 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
293 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
294 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
295
296 /* Mixed S64-double binary comparators */
297 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
298 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
299 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
300 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
301 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
302 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
303
304 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
305 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
306 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
307 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
308 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
309 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
310
311 /* unary */
312 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
313 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
314 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
315 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
316 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
317 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
318 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
319 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
320 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
321
322 /* logical */
323 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
324 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
325
326 /* load field ref */
327 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
328 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
329 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
330 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
331 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
332
333 /* load from immediate operand */
334 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
335 [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
336 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
337 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
338
339 /* cast */
340 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
341 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
342 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
343
344 /* get context ref */
345 [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
346 [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
347 [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
348 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
349 };
350 #endif /* #ifndef INTERPRETER_USE_SWITCH */
351
352 START_OP
353
354 OP(FILTER_OP_UNKNOWN):
355 OP(FILTER_OP_LOAD_FIELD_REF):
356 #ifdef INTERPRETER_USE_SWITCH
357 default:
358 #endif /* INTERPRETER_USE_SWITCH */
359 ERR("unknown bytecode op %u\n",
360 (unsigned int) *(filter_opcode_t *) pc);
361 ret = -EINVAL;
362 goto end;
363
364 OP(FILTER_OP_RETURN):
365 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
366 retval = !!estack_ax_v;
367 ret = 0;
368 goto end;
369
370 /* binary */
371 OP(FILTER_OP_MUL):
372 OP(FILTER_OP_DIV):
373 OP(FILTER_OP_MOD):
374 OP(FILTER_OP_PLUS):
375 OP(FILTER_OP_MINUS):
376 OP(FILTER_OP_RSHIFT):
377 OP(FILTER_OP_LSHIFT):
378 OP(FILTER_OP_BIN_AND):
379 OP(FILTER_OP_BIN_OR):
380 OP(FILTER_OP_BIN_XOR):
381 ERR("unsupported bytecode op %u\n",
382 (unsigned int) *(filter_opcode_t *) pc);
383 ret = -EINVAL;
384 goto end;
385
386 OP(FILTER_OP_EQ):
387 {
388 /* Dynamic typing. */
389 switch (estack_ax_t) {
390 case REG_S64:
391 switch (estack_bx_t) {
392 case REG_S64:
393 JUMP_TO(FILTER_OP_EQ_S64);
394 case REG_DOUBLE:
395 JUMP_TO(FILTER_OP_EQ_DOUBLE_S64);
396 case REG_STRING: /* Fall-through */
397 case REG_STAR_GLOB_STRING:
398 ret = -EINVAL;
399 goto end;
400 default:
401 ERR("Unknown filter register type (%d)",
402 (int) estack_bx_t);
403 ret = -EINVAL;
404 goto end;
405 }
406 break;
407 case REG_DOUBLE:
408 switch (estack_bx_t) {
409 case REG_S64:
410 JUMP_TO(FILTER_OP_EQ_S64_DOUBLE);
411 case REG_DOUBLE:
412 JUMP_TO(FILTER_OP_EQ_DOUBLE);
413 case REG_STRING: /* Fall-through */
414 case REG_STAR_GLOB_STRING:
415 ret = -EINVAL;
416 goto end;
417 default:
418 ERR("Unknown filter register type (%d)",
419 (int) estack_bx_t);
420 ret = -EINVAL;
421 goto end;
422 }
423 break;
424 case REG_STRING:
425 switch (estack_bx_t) {
426 case REG_S64: /* Fall-through */
427 case REG_DOUBLE:
428 ret = -EINVAL;
429 goto end;
430 case REG_STRING:
431 JUMP_TO(FILTER_OP_EQ_STRING);
432 case REG_STAR_GLOB_STRING:
433 JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
434 default:
435 ERR("Unknown filter register type (%d)",
436 (int) estack_bx_t);
437 ret = -EINVAL;
438 goto end;
439 }
440 break;
441 case REG_STAR_GLOB_STRING:
442 switch (estack_bx_t) {
443 case REG_S64: /* Fall-through */
444 case REG_DOUBLE:
445 ret = -EINVAL;
446 goto end;
447 case REG_STRING:
448 JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
449 case REG_STAR_GLOB_STRING:
450 ret = -EINVAL;
451 goto end;
452 default:
453 ERR("Unknown filter register type (%d)",
454 (int) estack_bx_t);
455 ret = -EINVAL;
456 goto end;
457 }
458 break;
459 default:
460 ERR("Unknown filter register type (%d)",
461 (int) estack_ax_t);
462 ret = -EINVAL;
463 goto end;
464 }
465 }
466 OP(FILTER_OP_NE):
467 {
468 /* Dynamic typing. */
469 switch (estack_ax_t) {
470 case REG_S64:
471 switch (estack_bx_t) {
472 case REG_S64:
473 JUMP_TO(FILTER_OP_NE_S64);
474 case REG_DOUBLE:
475 JUMP_TO(FILTER_OP_NE_DOUBLE_S64);
476 case REG_STRING: /* Fall-through */
477 case REG_STAR_GLOB_STRING:
478 ret = -EINVAL;
479 goto end;
480 default:
481 ERR("Unknown filter register type (%d)",
482 (int) estack_bx_t);
483 ret = -EINVAL;
484 goto end;
485 }
486 break;
487 case REG_DOUBLE:
488 switch (estack_bx_t) {
489 case REG_S64:
490 JUMP_TO(FILTER_OP_NE_S64_DOUBLE);
491 case REG_DOUBLE:
492 JUMP_TO(FILTER_OP_NE_DOUBLE);
493 case REG_STRING: /* Fall-through */
494 case REG_STAR_GLOB_STRING:
495 ret = -EINVAL;
496 goto end;
497 default:
498 ERR("Unknown filter register type (%d)",
499 (int) estack_bx_t);
500 ret = -EINVAL;
501 goto end;
502 }
503 break;
504 case REG_STRING:
505 switch (estack_bx_t) {
506 case REG_S64: /* Fall-through */
507 case REG_DOUBLE:
508 ret = -EINVAL;
509 goto end;
510 case REG_STRING:
511 JUMP_TO(FILTER_OP_NE_STRING);
512 case REG_STAR_GLOB_STRING:
513 JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
514 default:
515 ERR("Unknown filter register type (%d)",
516 (int) estack_bx_t);
517 ret = -EINVAL;
518 goto end;
519 }
520 break;
521 case REG_STAR_GLOB_STRING:
522 switch (estack_bx_t) {
523 case REG_S64: /* Fall-through */
524 case REG_DOUBLE:
525 ret = -EINVAL;
526 goto end;
527 case REG_STRING:
528 JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
529 case REG_STAR_GLOB_STRING:
530 ret = -EINVAL;
531 goto end;
532 default:
533 ERR("Unknown filter register type (%d)",
534 (int) estack_bx_t);
535 ret = -EINVAL;
536 goto end;
537 }
538 break;
539 default:
540 ERR("Unknown filter register type (%d)",
541 (int) estack_ax_t);
542 ret = -EINVAL;
543 goto end;
544 }
545 }
546 OP(FILTER_OP_GT):
547 {
548 /* Dynamic typing. */
549 switch (estack_ax_t) {
550 case REG_S64:
551 switch (estack_bx_t) {
552 case REG_S64:
553 JUMP_TO(FILTER_OP_GT_S64);
554 case REG_DOUBLE:
555 JUMP_TO(FILTER_OP_GT_DOUBLE_S64);
556 case REG_STRING: /* Fall-through */
557 case REG_STAR_GLOB_STRING:
558 ret = -EINVAL;
559 goto end;
560 default:
561 ERR("Unknown filter register type (%d)",
562 (int) estack_bx_t);
563 ret = -EINVAL;
564 goto end;
565 }
566 break;
567 case REG_DOUBLE:
568 switch (estack_bx_t) {
569 case REG_S64:
570 JUMP_TO(FILTER_OP_GT_S64_DOUBLE);
571 case REG_DOUBLE:
572 JUMP_TO(FILTER_OP_GT_DOUBLE);
573 case REG_STRING: /* Fall-through */
574 case REG_STAR_GLOB_STRING:
575 ret = -EINVAL;
576 goto end;
577 default:
578 ERR("Unknown filter register type (%d)",
579 (int) estack_bx_t);
580 ret = -EINVAL;
581 goto end;
582 }
583 break;
584 case REG_STRING:
585 switch (estack_bx_t) {
586 case REG_S64: /* Fall-through */
587 case REG_DOUBLE: /* Fall-through */
588 case REG_STAR_GLOB_STRING:
589 ret = -EINVAL;
590 goto end;
591 case REG_STRING:
592 JUMP_TO(FILTER_OP_GT_STRING);
593 default:
594 ERR("Unknown filter register type (%d)",
595 (int) estack_bx_t);
596 ret = -EINVAL;
597 goto end;
598 }
599 break;
600 default:
601 ERR("Unknown filter register type (%d)",
602 (int) estack_ax_t);
603 ret = -EINVAL;
604 goto end;
605 }
606 }
607 OP(FILTER_OP_LT):
608 {
609 /* Dynamic typing. */
610 switch (estack_ax_t) {
611 case REG_S64:
612 switch (estack_bx_t) {
613 case REG_S64:
614 JUMP_TO(FILTER_OP_LT_S64);
615 case REG_DOUBLE:
616 JUMP_TO(FILTER_OP_LT_DOUBLE_S64);
617 case REG_STRING: /* Fall-through */
618 case REG_STAR_GLOB_STRING:
619 ret = -EINVAL;
620 goto end;
621 default:
622 ERR("Unknown filter register type (%d)",
623 (int) estack_bx_t);
624 ret = -EINVAL;
625 goto end;
626 }
627 break;
628 case REG_DOUBLE:
629 switch (estack_bx_t) {
630 case REG_S64:
631 JUMP_TO(FILTER_OP_LT_S64_DOUBLE);
632 case REG_DOUBLE:
633 JUMP_TO(FILTER_OP_LT_DOUBLE);
634 case REG_STRING: /* Fall-through */
635 case REG_STAR_GLOB_STRING:
636 ret = -EINVAL;
637 goto end;
638 default:
639 ERR("Unknown filter register type (%d)",
640 (int) estack_bx_t);
641 ret = -EINVAL;
642 goto end;
643 }
644 break;
645 case REG_STRING:
646 switch (estack_bx_t) {
647 case REG_S64: /* Fall-through */
648 case REG_DOUBLE: /* Fall-through */
649 case REG_STAR_GLOB_STRING:
650 ret = -EINVAL;
651 goto end;
652 case REG_STRING:
653 JUMP_TO(FILTER_OP_LT_STRING);
654 default:
655 ERR("Unknown filter register type (%d)",
656 (int) estack_bx_t);
657 ret = -EINVAL;
658 goto end;
659 }
660 break;
661 default:
662 ERR("Unknown filter register type (%d)",
663 (int) estack_ax_t);
664 ret = -EINVAL;
665 goto end;
666 }
667 }
668 OP(FILTER_OP_GE):
669 {
670 /* Dynamic typing. */
671 switch (estack_ax_t) {
672 case REG_S64:
673 switch (estack_bx_t) {
674 case REG_S64:
675 JUMP_TO(FILTER_OP_GE_S64);
676 case REG_DOUBLE:
677 JUMP_TO(FILTER_OP_GE_DOUBLE_S64);
678 case REG_STRING: /* Fall-through */
679 case REG_STAR_GLOB_STRING:
680 ret = -EINVAL;
681 goto end;
682 default:
683 ERR("Unknown filter register type (%d)",
684 (int) estack_bx_t);
685 ret = -EINVAL;
686 goto end;
687 }
688 break;
689 case REG_DOUBLE:
690 switch (estack_bx_t) {
691 case REG_S64:
692 JUMP_TO(FILTER_OP_GE_S64_DOUBLE);
693 case REG_DOUBLE:
694 JUMP_TO(FILTER_OP_GE_DOUBLE);
695 case REG_STRING: /* Fall-through */
696 case REG_STAR_GLOB_STRING:
697 ret = -EINVAL;
698 goto end;
699 default:
700 ERR("Unknown filter register type (%d)",
701 (int) estack_bx_t);
702 ret = -EINVAL;
703 goto end;
704 }
705 break;
706 case REG_STRING:
707 switch (estack_bx_t) {
708 case REG_S64: /* Fall-through */
709 case REG_DOUBLE: /* Fall-through */
710 case REG_STAR_GLOB_STRING:
711 ret = -EINVAL;
712 goto end;
713 case REG_STRING:
714 JUMP_TO(FILTER_OP_GE_STRING);
715 default:
716 ERR("Unknown filter register type (%d)",
717 (int) estack_bx_t);
718 ret = -EINVAL;
719 goto end;
720 }
721 break;
722 default:
723 ERR("Unknown filter register type (%d)",
724 (int) estack_ax_t);
725 ret = -EINVAL;
726 goto end;
727 }
728 }
729 OP(FILTER_OP_LE):
730 {
731 /* Dynamic typing. */
732 switch (estack_ax_t) {
733 case REG_S64:
734 switch (estack_bx_t) {
735 case REG_S64:
736 JUMP_TO(FILTER_OP_LE_S64);
737 case REG_DOUBLE:
738 JUMP_TO(FILTER_OP_LE_DOUBLE_S64);
739 case REG_STRING: /* Fall-through */
740 case REG_STAR_GLOB_STRING:
741 ret = -EINVAL;
742 goto end;
743 default:
744 ERR("Unknown filter register type (%d)",
745 (int) estack_bx_t);
746 ret = -EINVAL;
747 goto end;
748 }
749 break;
750 case REG_DOUBLE:
751 switch (estack_bx_t) {
752 case REG_S64:
753 JUMP_TO(FILTER_OP_LE_S64_DOUBLE);
754 case REG_DOUBLE:
755 JUMP_TO(FILTER_OP_LE_DOUBLE);
756 case REG_STRING: /* Fall-through */
757 case REG_STAR_GLOB_STRING:
758 ret = -EINVAL;
759 goto end;
760 default:
761 ERR("Unknown filter register type (%d)",
762 (int) estack_bx_t);
763 ret = -EINVAL;
764 goto end;
765 }
766 break;
767 case REG_STRING:
768 switch (estack_bx_t) {
769 case REG_S64: /* Fall-through */
770 case REG_DOUBLE: /* Fall-through */
771 case REG_STAR_GLOB_STRING:
772 ret = -EINVAL;
773 goto end;
774 case REG_STRING:
775 JUMP_TO(FILTER_OP_LE_STRING);
776 default:
777 ERR("Unknown filter register type (%d)",
778 (int) estack_bx_t);
779 ret = -EINVAL;
780 goto end;
781 }
782 break;
783 default:
784 ERR("Unknown filter register type (%d)",
785 (int) estack_ax_t);
786 ret = -EINVAL;
787 goto end;
788 }
789 }
790
791 OP(FILTER_OP_EQ_STRING):
792 {
793 int res;
794
795 res = (stack_strcmp(stack, top, "==") == 0);
796 estack_pop(stack, top, ax, bx, ax_t, bx_t);
797 estack_ax_v = res;
798 estack_ax_t = REG_S64;
799 next_pc += sizeof(struct binary_op);
800 PO;
801 }
802 OP(FILTER_OP_NE_STRING):
803 {
804 int res;
805
806 res = (stack_strcmp(stack, top, "!=") != 0);
807 estack_pop(stack, top, ax, bx, ax_t, bx_t);
808 estack_ax_v = res;
809 estack_ax_t = REG_S64;
810 next_pc += sizeof(struct binary_op);
811 PO;
812 }
813 OP(FILTER_OP_GT_STRING):
814 {
815 int res;
816
817 res = (stack_strcmp(stack, top, ">") > 0);
818 estack_pop(stack, top, ax, bx, ax_t, bx_t);
819 estack_ax_v = res;
820 estack_ax_t = REG_S64;
821 next_pc += sizeof(struct binary_op);
822 PO;
823 }
824 OP(FILTER_OP_LT_STRING):
825 {
826 int res;
827
828 res = (stack_strcmp(stack, top, "<") < 0);
829 estack_pop(stack, top, ax, bx, ax_t, bx_t);
830 estack_ax_v = res;
831 estack_ax_t = REG_S64;
832 next_pc += sizeof(struct binary_op);
833 PO;
834 }
835 OP(FILTER_OP_GE_STRING):
836 {
837 int res;
838
839 res = (stack_strcmp(stack, top, ">=") >= 0);
840 estack_pop(stack, top, ax, bx, ax_t, bx_t);
841 estack_ax_v = res;
842 estack_ax_t = REG_S64;
843 next_pc += sizeof(struct binary_op);
844 PO;
845 }
846 OP(FILTER_OP_LE_STRING):
847 {
848 int res;
849
850 res = (stack_strcmp(stack, top, "<=") <= 0);
851 estack_pop(stack, top, ax, bx, ax_t, bx_t);
852 estack_ax_v = res;
853 estack_ax_t = REG_S64;
854 next_pc += sizeof(struct binary_op);
855 PO;
856 }
857
858 OP(FILTER_OP_EQ_STAR_GLOB_STRING):
859 {
860 int res;
861
862 res = (stack_star_glob_match(stack, top, "==") == 0);
863 estack_pop(stack, top, ax, bx, ax_t, bx_t);
864 estack_ax_v = res;
865 estack_ax_t = REG_S64;
866 next_pc += sizeof(struct binary_op);
867 PO;
868 }
869 OP(FILTER_OP_NE_STAR_GLOB_STRING):
870 {
871 int res;
872
873 res = (stack_star_glob_match(stack, top, "!=") != 0);
874 estack_pop(stack, top, ax, bx, ax_t, bx_t);
875 estack_ax_v = res;
876 estack_ax_t = REG_S64;
877 next_pc += sizeof(struct binary_op);
878 PO;
879 }
880
881 OP(FILTER_OP_EQ_S64):
882 {
883 int res;
884
885 res = (estack_bx_v == estack_ax_v);
886 estack_pop(stack, top, ax, bx, ax_t, bx_t);
887 estack_ax_v = res;
888 estack_ax_t = REG_S64;
889 next_pc += sizeof(struct binary_op);
890 PO;
891 }
892 OP(FILTER_OP_NE_S64):
893 {
894 int res;
895
896 res = (estack_bx_v != estack_ax_v);
897 estack_pop(stack, top, ax, bx, ax_t, bx_t);
898 estack_ax_v = res;
899 estack_ax_t = REG_S64;
900 next_pc += sizeof(struct binary_op);
901 PO;
902 }
903 OP(FILTER_OP_GT_S64):
904 {
905 int res;
906
907 res = (estack_bx_v > estack_ax_v);
908 estack_pop(stack, top, ax, bx, ax_t, bx_t);
909 estack_ax_v = res;
910 estack_ax_t = REG_S64;
911 next_pc += sizeof(struct binary_op);
912 PO;
913 }
914 OP(FILTER_OP_LT_S64):
915 {
916 int res;
917
918 res = (estack_bx_v < estack_ax_v);
919 estack_pop(stack, top, ax, bx, ax_t, bx_t);
920 estack_ax_v = res;
921 estack_ax_t = REG_S64;
922 next_pc += sizeof(struct binary_op);
923 PO;
924 }
925 OP(FILTER_OP_GE_S64):
926 {
927 int res;
928
929 res = (estack_bx_v >= estack_ax_v);
930 estack_pop(stack, top, ax, bx, ax_t, bx_t);
931 estack_ax_v = res;
932 estack_ax_t = REG_S64;
933 next_pc += sizeof(struct binary_op);
934 PO;
935 }
936 OP(FILTER_OP_LE_S64):
937 {
938 int res;
939
940 res = (estack_bx_v <= estack_ax_v);
941 estack_pop(stack, top, ax, bx, ax_t, bx_t);
942 estack_ax_v = res;
943 estack_ax_t = REG_S64;
944 next_pc += sizeof(struct binary_op);
945 PO;
946 }
947
948 OP(FILTER_OP_EQ_DOUBLE):
949 {
950 int res;
951
952 res = (estack_bx(stack, top)->u.d == estack_ax(stack, top)->u.d);
953 estack_pop(stack, top, ax, bx, ax_t, bx_t);
954 estack_ax_v = res;
955 estack_ax_t = REG_S64;
956 next_pc += sizeof(struct binary_op);
957 PO;
958 }
959 OP(FILTER_OP_NE_DOUBLE):
960 {
961 int res;
962
963 res = (estack_bx(stack, top)->u.d != estack_ax(stack, top)->u.d);
964 estack_pop(stack, top, ax, bx, ax_t, bx_t);
965 estack_ax_v = res;
966 estack_ax_t = REG_S64;
967 next_pc += sizeof(struct binary_op);
968 PO;
969 }
970 OP(FILTER_OP_GT_DOUBLE):
971 {
972 int res;
973
974 res = (estack_bx(stack, top)->u.d > estack_ax(stack, top)->u.d);
975 estack_pop(stack, top, ax, bx, ax_t, bx_t);
976 estack_ax_v = res;
977 estack_ax_t = REG_S64;
978 next_pc += sizeof(struct binary_op);
979 PO;
980 }
981 OP(FILTER_OP_LT_DOUBLE):
982 {
983 int res;
984
985 res = (estack_bx(stack, top)->u.d < estack_ax(stack, top)->u.d);
986 estack_pop(stack, top, ax, bx, ax_t, bx_t);
987 estack_ax_v = res;
988 estack_ax_t = REG_S64;
989 next_pc += sizeof(struct binary_op);
990 PO;
991 }
992 OP(FILTER_OP_GE_DOUBLE):
993 {
994 int res;
995
996 res = (estack_bx(stack, top)->u.d >= estack_ax(stack, top)->u.d);
997 estack_pop(stack, top, ax, bx, ax_t, bx_t);
998 estack_ax_v = res;
999 estack_ax_t = REG_S64;
1000 next_pc += sizeof(struct binary_op);
1001 PO;
1002 }
1003 OP(FILTER_OP_LE_DOUBLE):
1004 {
1005 int res;
1006
1007 res = (estack_bx(stack, top)->u.d <= estack_ax(stack, top)->u.d);
1008 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1009 estack_ax_v = res;
1010 estack_ax_t = REG_S64;
1011 next_pc += sizeof(struct binary_op);
1012 PO;
1013 }
1014
1015 /* Mixed S64-double binary comparators */
1016 OP(FILTER_OP_EQ_DOUBLE_S64):
1017 {
1018 int res;
1019
1020 res = (estack_bx(stack, top)->u.d == estack_ax_v);
1021 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1022 estack_ax_v = res;
1023 estack_ax_t = REG_S64;
1024 next_pc += sizeof(struct binary_op);
1025 PO;
1026 }
1027 OP(FILTER_OP_NE_DOUBLE_S64):
1028 {
1029 int res;
1030
1031 res = (estack_bx(stack, top)->u.d != estack_ax_v);
1032 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1033 estack_ax_v = res;
1034 estack_ax_t = REG_S64;
1035 next_pc += sizeof(struct binary_op);
1036 PO;
1037 }
1038 OP(FILTER_OP_GT_DOUBLE_S64):
1039 {
1040 int res;
1041
1042 res = (estack_bx(stack, top)->u.d > estack_ax_v);
1043 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1044 estack_ax_v = res;
1045 estack_ax_t = REG_S64;
1046 next_pc += sizeof(struct binary_op);
1047 PO;
1048 }
1049 OP(FILTER_OP_LT_DOUBLE_S64):
1050 {
1051 int res;
1052
1053 res = (estack_bx(stack, top)->u.d < estack_ax_v);
1054 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1055 estack_ax_v = res;
1056 estack_ax_t = REG_S64;
1057 next_pc += sizeof(struct binary_op);
1058 PO;
1059 }
1060 OP(FILTER_OP_GE_DOUBLE_S64):
1061 {
1062 int res;
1063
1064 res = (estack_bx(stack, top)->u.d >= estack_ax_v);
1065 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1066 estack_ax_v = res;
1067 estack_ax_t = REG_S64;
1068 next_pc += sizeof(struct binary_op);
1069 PO;
1070 }
1071 OP(FILTER_OP_LE_DOUBLE_S64):
1072 {
1073 int res;
1074
1075 res = (estack_bx(stack, top)->u.d <= estack_ax_v);
1076 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1077 estack_ax_v = res;
1078 estack_ax_t = REG_S64;
1079 next_pc += sizeof(struct binary_op);
1080 PO;
1081 }
1082
1083 OP(FILTER_OP_EQ_S64_DOUBLE):
1084 {
1085 int res;
1086
1087 res = (estack_bx_v == estack_ax(stack, top)->u.d);
1088 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1089 estack_ax_v = res;
1090 estack_ax_t = REG_S64;
1091 next_pc += sizeof(struct binary_op);
1092 PO;
1093 }
1094 OP(FILTER_OP_NE_S64_DOUBLE):
1095 {
1096 int res;
1097
1098 res = (estack_bx_v != estack_ax(stack, top)->u.d);
1099 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1100 estack_ax_v = res;
1101 estack_ax_t = REG_S64;
1102 next_pc += sizeof(struct binary_op);
1103 PO;
1104 }
1105 OP(FILTER_OP_GT_S64_DOUBLE):
1106 {
1107 int res;
1108
1109 res = (estack_bx_v > estack_ax(stack, top)->u.d);
1110 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1111 estack_ax_v = res;
1112 estack_ax_t = REG_S64;
1113 next_pc += sizeof(struct binary_op);
1114 PO;
1115 }
1116 OP(FILTER_OP_LT_S64_DOUBLE):
1117 {
1118 int res;
1119
1120 res = (estack_bx_v < estack_ax(stack, top)->u.d);
1121 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1122 estack_ax_v = res;
1123 estack_ax_t = REG_S64;
1124 next_pc += sizeof(struct binary_op);
1125 PO;
1126 }
1127 OP(FILTER_OP_GE_S64_DOUBLE):
1128 {
1129 int res;
1130
1131 res = (estack_bx_v >= estack_ax(stack, top)->u.d);
1132 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1133 estack_ax_v = res;
1134 estack_ax_t = REG_S64;
1135 next_pc += sizeof(struct binary_op);
1136 PO;
1137 }
1138 OP(FILTER_OP_LE_S64_DOUBLE):
1139 {
1140 int res;
1141
1142 res = (estack_bx_v <= estack_ax(stack, top)->u.d);
1143 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1144 estack_ax_v = res;
1145 estack_ax_t = REG_S64;
1146 next_pc += sizeof(struct binary_op);
1147 PO;
1148 }
1149
1150 /* unary */
1151 OP(FILTER_OP_UNARY_PLUS):
1152 {
1153 /* Dynamic typing. */
1154 switch (estack_ax_t) {
1155 case REG_S64: /* Fall-through. */
1156 JUMP_TO(FILTER_OP_UNARY_PLUS_S64);
1157 case REG_DOUBLE:
1158 JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE);
1159 case REG_STRING: /* Fall-through */
1160 case REG_STAR_GLOB_STRING:
1161 ret = -EINVAL;
1162 goto end;
1163 default:
1164 ERR("Unknown filter register type (%d)",
1165 (int) estack_ax_t);
1166 ret = -EINVAL;
1167 goto end;
1168 }
1169 }
1170 OP(FILTER_OP_UNARY_MINUS):
1171 {
1172 /* Dynamic typing. */
1173 switch (estack_ax_t) {
1174 case REG_S64:
1175 JUMP_TO(FILTER_OP_UNARY_MINUS_S64);
1176 case REG_DOUBLE:
1177 JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE);
1178 case REG_STRING: /* Fall-through */
1179 case REG_STAR_GLOB_STRING:
1180 ret = -EINVAL;
1181 goto end;
1182 default:
1183 ERR("Unknown filter register type (%d)",
1184 (int) estack_ax_t);
1185 ret = -EINVAL;
1186 goto end;
1187 }
1188 }
1189 OP(FILTER_OP_UNARY_NOT):
1190 {
1191 /* Dynamic typing. */
1192 switch (estack_ax_t) {
1193 case REG_S64:
1194 JUMP_TO(FILTER_OP_UNARY_NOT_S64);
1195 case REG_DOUBLE:
1196 JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE);
1197 case REG_STRING: /* Fall-through */
1198 case REG_STAR_GLOB_STRING:
1199 ret = -EINVAL;
1200 goto end;
1201 default:
1202 ERR("Unknown filter register type (%d)",
1203 (int) estack_ax_t);
1204 ret = -EINVAL;
1205 goto end;
1206 }
1207 next_pc += sizeof(struct unary_op);
1208 PO;
1209 }
1210
1211 OP(FILTER_OP_UNARY_PLUS_S64):
1212 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
1213 {
1214 next_pc += sizeof(struct unary_op);
1215 PO;
1216 }
1217 OP(FILTER_OP_UNARY_MINUS_S64):
1218 {
1219 estack_ax_v = -estack_ax_v;
1220 next_pc += sizeof(struct unary_op);
1221 PO;
1222 }
1223 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
1224 {
1225 estack_ax(stack, top)->u.d = -estack_ax(stack, top)->u.d;
1226 next_pc += sizeof(struct unary_op);
1227 PO;
1228 }
1229 OP(FILTER_OP_UNARY_NOT_S64):
1230 {
1231 estack_ax_v = !estack_ax_v;
1232 next_pc += sizeof(struct unary_op);
1233 PO;
1234 }
1235 OP(FILTER_OP_UNARY_NOT_DOUBLE):
1236 {
1237 estack_ax_v = !estack_ax(stack, top)->u.d;
1238 estack_ax_t = REG_S64;
1239 next_pc += sizeof(struct unary_op);
1240 PO;
1241 }
1242
1243 /* logical */
1244 OP(FILTER_OP_AND):
1245 {
1246 struct logical_op *insn = (struct logical_op *) pc;
1247
1248 if (estack_ax_t != REG_S64) {
1249 ret = -EINVAL;
1250 goto end;
1251 }
1252 /* If AX is 0, skip and evaluate to 0 */
1253 if (unlikely(estack_ax_v == 0)) {
1254 dbg_printf("Jumping to bytecode offset %u\n",
1255 (unsigned int) insn->skip_offset);
1256 next_pc = start_pc + insn->skip_offset;
1257 } else {
1258 /* Pop 1 when jump not taken */
1259 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1260 next_pc += sizeof(struct logical_op);
1261 }
1262 PO;
1263 }
1264 OP(FILTER_OP_OR):
1265 {
1266 struct logical_op *insn = (struct logical_op *) pc;
1267
1268 if (estack_ax_t != REG_S64) {
1269 ret = -EINVAL;
1270 goto end;
1271 }
1272 /* If AX is nonzero, skip and evaluate to 1 */
1273 if (unlikely(estack_ax_v != 0)) {
1274 estack_ax_v = 1;
1275 dbg_printf("Jumping to bytecode offset %u\n",
1276 (unsigned int) insn->skip_offset);
1277 next_pc = start_pc + insn->skip_offset;
1278 } else {
1279 /* Pop 1 when jump not taken */
1280 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1281 next_pc += sizeof(struct logical_op);
1282 }
1283 PO;
1284 }
1285
1286
1287 /* load field ref */
1288 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
1289 {
1290 struct load_op *insn = (struct load_op *) pc;
1291 struct field_ref *ref = (struct field_ref *) insn->data;
1292
1293 dbg_printf("load field ref offset %u type string\n",
1294 ref->offset);
1295 estack_push(stack, top, ax, bx, ax_t, bx_t);
1296 estack_ax(stack, top)->u.s.str =
1297 *(const char * const *) &filter_stack_data[ref->offset];
1298 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1299 dbg_printf("Filter warning: loading a NULL string.\n");
1300 ret = -EINVAL;
1301 goto end;
1302 }
1303 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
1304 estack_ax(stack, top)->u.s.literal_type =
1305 ESTACK_STRING_LITERAL_TYPE_NONE;
1306 estack_ax_t = REG_STRING;
1307 dbg_printf("ref load string %s\n", estack_ax(stack, top)->u.s.str);
1308 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1309 PO;
1310 }
1311
1312 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
1313 {
1314 struct load_op *insn = (struct load_op *) pc;
1315 struct field_ref *ref = (struct field_ref *) insn->data;
1316
1317 dbg_printf("load field ref offset %u type sequence\n",
1318 ref->offset);
1319 estack_push(stack, top, ax, bx, ax_t, bx_t);
1320 estack_ax(stack, top)->u.s.seq_len =
1321 *(unsigned long *) &filter_stack_data[ref->offset];
1322 estack_ax(stack, top)->u.s.str =
1323 *(const char **) (&filter_stack_data[ref->offset
1324 + sizeof(unsigned long)]);
1325 estack_ax_t = REG_STRING;
1326 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1327 dbg_printf("Filter warning: loading a NULL sequence.\n");
1328 ret = -EINVAL;
1329 goto end;
1330 }
1331 estack_ax(stack, top)->u.s.literal_type =
1332 ESTACK_STRING_LITERAL_TYPE_NONE;
1333 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1334 PO;
1335 }
1336
1337 OP(FILTER_OP_LOAD_FIELD_REF_S64):
1338 {
1339 struct load_op *insn = (struct load_op *) pc;
1340 struct field_ref *ref = (struct field_ref *) insn->data;
1341
1342 dbg_printf("load field ref offset %u type s64\n",
1343 ref->offset);
1344 estack_push(stack, top, ax, bx, ax_t, bx_t);
1345 estack_ax_v =
1346 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
1347 estack_ax_t = REG_S64;
1348 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax_v);
1349 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1350 PO;
1351 }
1352
1353 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
1354 {
1355 struct load_op *insn = (struct load_op *) pc;
1356 struct field_ref *ref = (struct field_ref *) insn->data;
1357
1358 dbg_printf("load field ref offset %u type double\n",
1359 ref->offset);
1360 estack_push(stack, top, ax, bx, ax_t, bx_t);
1361 memcpy(&estack_ax(stack, top)->u.d, &filter_stack_data[ref->offset],
1362 sizeof(struct literal_double));
1363 estack_ax_t = REG_DOUBLE;
1364 dbg_printf("ref load double %g\n", estack_ax(stack, top)->u.d);
1365 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1366 PO;
1367 }
1368
1369 /* load from immediate operand */
1370 OP(FILTER_OP_LOAD_STRING):
1371 {
1372 struct load_op *insn = (struct load_op *) pc;
1373
1374 dbg_printf("load string %s\n", insn->data);
1375 estack_push(stack, top, ax, bx, ax_t, bx_t);
1376 estack_ax(stack, top)->u.s.str = insn->data;
1377 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
1378 estack_ax(stack, top)->u.s.literal_type =
1379 ESTACK_STRING_LITERAL_TYPE_PLAIN;
1380 estack_ax_t = REG_STRING;
1381 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1382 PO;
1383 }
1384
1385 OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
1386 {
1387 struct load_op *insn = (struct load_op *) pc;
1388
1389 dbg_printf("load globbing pattern %s\n", insn->data);
1390 estack_push(stack, top, ax, bx, ax_t, bx_t);
1391 estack_ax(stack, top)->u.s.str = insn->data;
1392 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
1393 estack_ax(stack, top)->u.s.literal_type =
1394 ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
1395 estack_ax_t = REG_STAR_GLOB_STRING;
1396 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1397 PO;
1398 }
1399
1400 OP(FILTER_OP_LOAD_S64):
1401 {
1402 struct load_op *insn = (struct load_op *) pc;
1403
1404 estack_push(stack, top, ax, bx, ax_t, bx_t);
1405 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
1406 estack_ax_t = REG_S64;
1407 dbg_printf("load s64 %" PRIi64 "\n", estack_ax_v);
1408 next_pc += sizeof(struct load_op)
1409 + sizeof(struct literal_numeric);
1410 PO;
1411 }
1412
1413 OP(FILTER_OP_LOAD_DOUBLE):
1414 {
1415 struct load_op *insn = (struct load_op *) pc;
1416
1417 estack_push(stack, top, ax, bx, ax_t, bx_t);
1418 memcpy(&estack_ax(stack, top)->u.d, insn->data,
1419 sizeof(struct literal_double));
1420 estack_ax_t = REG_DOUBLE;
1421 dbg_printf("load double %g\n", estack_ax(stack, top)->u.d);
1422 next_pc += sizeof(struct load_op)
1423 + sizeof(struct literal_double);
1424 PO;
1425 }
1426
1427 /* cast */
1428 OP(FILTER_OP_CAST_TO_S64):
1429 {
1430 /* Dynamic typing. */
1431 switch (estack_ax_t) {
1432 case REG_S64:
1433 JUMP_TO(FILTER_OP_CAST_NOP);
1434 case REG_DOUBLE:
1435 JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64);
1436 case REG_STRING: /* Fall-through */
1437 case REG_STAR_GLOB_STRING:
1438 ret = -EINVAL;
1439 goto end;
1440 default:
1441 ERR("Unknown filter register type (%d)",
1442 (int) estack_ax_t);
1443 ret = -EINVAL;
1444 goto end;
1445 }
1446 }
1447
1448 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
1449 {
1450 estack_ax_v = (int64_t) estack_ax(stack, top)->u.d;
1451 estack_ax_t = REG_S64;
1452 next_pc += sizeof(struct cast_op);
1453 PO;
1454 }
1455
1456 OP(FILTER_OP_CAST_NOP):
1457 {
1458 next_pc += sizeof(struct cast_op);
1459 PO;
1460 }
1461
1462 /* get context ref */
1463 OP(FILTER_OP_GET_CONTEXT_REF):
1464 {
1465 struct load_op *insn = (struct load_op *) pc;
1466 struct field_ref *ref = (struct field_ref *) insn->data;
1467 struct lttng_ctx *ctx;
1468 struct lttng_ctx_field *ctx_field;
1469 struct lttng_ctx_value v;
1470
1471 dbg_printf("get context ref offset %u type dynamic\n",
1472 ref->offset);
1473 ctx = rcu_dereference(session->ctx);
1474 ctx_field = &ctx->fields[ref->offset];
1475 ctx_field->get_value(ctx_field, &v);
1476 estack_push(stack, top, ax, bx, ax_t, bx_t);
1477 switch (v.sel) {
1478 case LTTNG_UST_DYNAMIC_TYPE_NONE:
1479 ret = -EINVAL;
1480 goto end;
1481 case LTTNG_UST_DYNAMIC_TYPE_S64:
1482 estack_ax_v = v.u.s64;
1483 estack_ax_t = REG_S64;
1484 dbg_printf("ref get context dynamic s64 %" PRIi64 "\n", estack_ax_v);
1485 break;
1486 case LTTNG_UST_DYNAMIC_TYPE_DOUBLE:
1487 estack_ax(stack, top)->u.d = v.u.d;
1488 estack_ax_t = REG_DOUBLE;
1489 dbg_printf("ref get context dynamic double %g\n", estack_ax(stack, top)->u.d);
1490 break;
1491 case LTTNG_UST_DYNAMIC_TYPE_STRING:
1492 estack_ax(stack, top)->u.s.str = v.u.str;
1493 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1494 dbg_printf("Filter warning: loading a NULL string.\n");
1495 ret = -EINVAL;
1496 goto end;
1497 }
1498 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
1499 estack_ax(stack, top)->u.s.literal_type =
1500 ESTACK_STRING_LITERAL_TYPE_NONE;
1501 dbg_printf("ref get context dynamic string %s\n", estack_ax(stack, top)->u.s.str);
1502 estack_ax_t = REG_STRING;
1503 break;
1504 default:
1505 dbg_printf("Filter warning: unknown dynamic type (%d).\n", (int) v.sel);
1506 ret = -EINVAL;
1507 goto end;
1508 }
1509 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1510 PO;
1511 }
1512
1513 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
1514 {
1515 struct load_op *insn = (struct load_op *) pc;
1516 struct field_ref *ref = (struct field_ref *) insn->data;
1517 struct lttng_ctx *ctx;
1518 struct lttng_ctx_field *ctx_field;
1519 struct lttng_ctx_value v;
1520
1521 dbg_printf("get context ref offset %u type string\n",
1522 ref->offset);
1523 ctx = rcu_dereference(session->ctx);
1524 ctx_field = &ctx->fields[ref->offset];
1525 ctx_field->get_value(ctx_field, &v);
1526 estack_push(stack, top, ax, bx, ax_t, bx_t);
1527 estack_ax(stack, top)->u.s.str = v.u.str;
1528 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1529 dbg_printf("Filter warning: loading a NULL string.\n");
1530 ret = -EINVAL;
1531 goto end;
1532 }
1533 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
1534 estack_ax(stack, top)->u.s.literal_type =
1535 ESTACK_STRING_LITERAL_TYPE_NONE;
1536 estack_ax_t = REG_STRING;
1537 dbg_printf("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
1538 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1539 PO;
1540 }
1541
1542 OP(FILTER_OP_GET_CONTEXT_REF_S64):
1543 {
1544 struct load_op *insn = (struct load_op *) pc;
1545 struct field_ref *ref = (struct field_ref *) insn->data;
1546 struct lttng_ctx *ctx;
1547 struct lttng_ctx_field *ctx_field;
1548 struct lttng_ctx_value v;
1549
1550 dbg_printf("get context ref offset %u type s64\n",
1551 ref->offset);
1552 ctx = rcu_dereference(session->ctx);
1553 ctx_field = &ctx->fields[ref->offset];
1554 ctx_field->get_value(ctx_field, &v);
1555 estack_push(stack, top, ax, bx, ax_t, bx_t);
1556 estack_ax_v = v.u.s64;
1557 estack_ax_t = REG_S64;
1558 dbg_printf("ref get context s64 %" PRIi64 "\n", estack_ax_v);
1559 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1560 PO;
1561 }
1562
1563 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
1564 {
1565 struct load_op *insn = (struct load_op *) pc;
1566 struct field_ref *ref = (struct field_ref *) insn->data;
1567 struct lttng_ctx *ctx;
1568 struct lttng_ctx_field *ctx_field;
1569 struct lttng_ctx_value v;
1570
1571 dbg_printf("get context ref offset %u type double\n",
1572 ref->offset);
1573 ctx = rcu_dereference(session->ctx);
1574 ctx_field = &ctx->fields[ref->offset];
1575 ctx_field->get_value(ctx_field, &v);
1576 estack_push(stack, top, ax, bx, ax_t, bx_t);
1577 memcpy(&estack_ax(stack, top)->u.d, &v.u.d, sizeof(struct literal_double));
1578 estack_ax_t = REG_DOUBLE;
1579 dbg_printf("ref get context double %g\n", estack_ax(stack, top)->u.d);
1580 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1581 PO;
1582 }
1583
1584 END_OP
1585 end:
1586 /* return 0 (discard) on error */
1587 if (ret)
1588 return 0;
1589 return retval;
1590 }
1591
1592 #undef START_OP
1593 #undef OP
1594 #undef PO
1595 #undef END_OP
This page took 0.103044 seconds and 3 git commands to generate.