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