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