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