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