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