Fix: remove dead code from filter interpreter
[lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
1 /*
2 * lttng-filter-interpreter.c
3 *
4 * LTTng UST filter interpreter.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "lttng-filter.h"
24
25 /*
26 * -1: wildcard found.
27 * -2: unknown escape char.
28 * 0: normal char.
29 */
30
31 static
32 int parse_char(const char **p)
33 {
34 switch (**p) {
35 case '\\':
36 (*p)++;
37 switch (**p) {
38 case '\\':
39 case '*':
40 return 0;
41 default:
42 return -2;
43 }
44 case '*':
45 return -1;
46 default:
47 return 0;
48 }
49 }
50
51 static
52 int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
53 {
54 const char *p = estack_bx(stack, top)->u.s.str, *q = estack_ax(stack, top)->u.s.str;
55 int ret;
56 int diff;
57
58 for (;;) {
59 int escaped_r0 = 0;
60
61 if (unlikely(p - estack_bx(stack, top)->u.s.str >= estack_bx(stack, top)->u.s.seq_len || *p == '\0')) {
62 if (q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0') {
63 return 0;
64 } else {
65 if (estack_ax(stack, top)->u.s.literal) {
66 ret = parse_char(&q);
67 if (ret == -1)
68 return 0;
69 }
70 return -1;
71 }
72 }
73 if (unlikely(q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0')) {
74 if (estack_bx(stack, top)->u.s.literal) {
75 ret = parse_char(&p);
76 if (ret == -1)
77 return 0;
78 }
79 return 1;
80 }
81 if (estack_bx(stack, top)->u.s.literal) {
82 ret = parse_char(&p);
83 if (ret == -1) {
84 return 0;
85 } else if (ret == -2) {
86 escaped_r0 = 1;
87 }
88 /* else compare both char */
89 }
90 if (estack_ax(stack, top)->u.s.literal) {
91 ret = parse_char(&q);
92 if (ret == -1) {
93 return 0;
94 } else if (ret == -2) {
95 if (!escaped_r0)
96 return -1;
97 } else {
98 if (escaped_r0)
99 return 1;
100 }
101 } else {
102 if (escaped_r0)
103 return 1;
104 }
105 diff = *p - *q;
106 if (diff != 0)
107 break;
108 p++;
109 q++;
110 }
111 return diff;
112 }
113
114 uint64_t lttng_filter_false(void *filter_data,
115 const char *filter_stack_data)
116 {
117 return 0;
118 }
119
120 #ifdef INTERPRETER_USE_SWITCH
121
122 /*
123 * Fallback for compilers that do not support taking address of labels.
124 */
125
126 #define START_OP \
127 start_pc = &bytecode->data[0]; \
128 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
129 pc = next_pc) { \
130 dbg_printf("Executing op %s (%u)\n", \
131 print_op((unsigned int) *(filter_opcode_t *) pc), \
132 (unsigned int) *(filter_opcode_t *) pc); \
133 switch (*(filter_opcode_t *) pc) {
134
135 #define OP(name) case name
136
137 #define PO break
138
139 #define END_OP } \
140 }
141
142 #else
143
144 /*
145 * Dispatch-table based interpreter.
146 */
147
148 #define START_OP \
149 start_pc = &bytecode->data[0]; \
150 pc = next_pc = start_pc; \
151 if (unlikely(pc - start_pc >= bytecode->len)) \
152 goto end; \
153 goto *dispatch[*(filter_opcode_t *) pc];
154
155 #define OP(name) \
156 LABEL_##name
157
158 #define PO \
159 pc = next_pc; \
160 goto *dispatch[*(filter_opcode_t *) pc];
161
162 #define END_OP
163
164 #endif
165
166 /*
167 * Return 0 (discard), or raise the 0x1 flag (log event).
168 * Currently, other flags are kept for future extensions and have no
169 * effect.
170 */
171 uint64_t lttng_filter_interpret_bytecode(void *filter_data,
172 const char *filter_stack_data)
173 {
174 struct bytecode_runtime *bytecode = filter_data;
175 void *pc, *next_pc, *start_pc;
176 int ret = -EINVAL;
177 uint64_t retval = 0;
178 struct estack _stack;
179 struct estack *stack = &_stack;
180 register int64_t ax = 0, bx = 0;
181 register int top = FILTER_STACK_EMPTY;
182 #ifndef INTERPRETER_USE_SWITCH
183 static void *dispatch[NR_FILTER_OPS] = {
184 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
185
186 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
187
188 /* binary */
189 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
190 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
191 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
192 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
193 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
194 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
195 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
196 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
197 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
198 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
199
200 /* binary comparators */
201 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
202 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
203 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
204 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
205 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
206 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
207
208 /* string binary comparator */
209 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
210 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
211 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
212 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
213 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
214 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
215
216 /* s64 binary comparator */
217 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
218 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
219 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
220 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
221 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
222 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
223
224 /* double binary comparator */
225 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
226 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
227 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
228 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
229 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
230 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
231
232 /* Mixed S64-double binary comparators */
233 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
234 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
235 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
236 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
237 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
238 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
239
240 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
241 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
242 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
243 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
244 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
245 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
246
247 /* unary */
248 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
249 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
250 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
251 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
252 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
253 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
254 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
255 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
256 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
257
258 /* logical */
259 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
260 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
261
262 /* load field ref */
263 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
264 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
265 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
266 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
267 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
268
269 /* load from immediate operand */
270 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
271 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
272 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
273
274 /* cast */
275 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
276 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
277 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
278
279 /* get context ref */
280 [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
281 [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
282 [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
283 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
284 };
285 #endif /* #ifndef INTERPRETER_USE_SWITCH */
286
287 START_OP
288
289 OP(FILTER_OP_UNKNOWN):
290 OP(FILTER_OP_LOAD_FIELD_REF):
291 OP(FILTER_OP_GET_CONTEXT_REF):
292 #ifdef INTERPRETER_USE_SWITCH
293 default:
294 #endif /* INTERPRETER_USE_SWITCH */
295 ERR("unknown bytecode op %u\n",
296 (unsigned int) *(filter_opcode_t *) pc);
297 ret = -EINVAL;
298 goto end;
299
300 OP(FILTER_OP_RETURN):
301 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
302 retval = !!estack_ax_v;
303 ret = 0;
304 goto end;
305
306 /* binary */
307 OP(FILTER_OP_MUL):
308 OP(FILTER_OP_DIV):
309 OP(FILTER_OP_MOD):
310 OP(FILTER_OP_PLUS):
311 OP(FILTER_OP_MINUS):
312 OP(FILTER_OP_RSHIFT):
313 OP(FILTER_OP_LSHIFT):
314 OP(FILTER_OP_BIN_AND):
315 OP(FILTER_OP_BIN_OR):
316 OP(FILTER_OP_BIN_XOR):
317 ERR("unsupported bytecode op %u\n",
318 (unsigned int) *(filter_opcode_t *) pc);
319 ret = -EINVAL;
320 goto end;
321
322 OP(FILTER_OP_EQ):
323 OP(FILTER_OP_NE):
324 OP(FILTER_OP_GT):
325 OP(FILTER_OP_LT):
326 OP(FILTER_OP_GE):
327 OP(FILTER_OP_LE):
328 ERR("unsupported non-specialized bytecode op %u\n",
329 (unsigned int) *(filter_opcode_t *) pc);
330 ret = -EINVAL;
331 goto end;
332
333 OP(FILTER_OP_EQ_STRING):
334 {
335 int res;
336
337 res = (stack_strcmp(stack, top, "==") == 0);
338 estack_pop(stack, top, ax, bx);
339 estack_ax_v = res;
340 next_pc += sizeof(struct binary_op);
341 PO;
342 }
343 OP(FILTER_OP_NE_STRING):
344 {
345 int res;
346
347 res = (stack_strcmp(stack, top, "!=") != 0);
348 estack_pop(stack, top, ax, bx);
349 estack_ax_v = res;
350 next_pc += sizeof(struct binary_op);
351 PO;
352 }
353 OP(FILTER_OP_GT_STRING):
354 {
355 int res;
356
357 res = (stack_strcmp(stack, top, ">") > 0);
358 estack_pop(stack, top, ax, bx);
359 estack_ax_v = res;
360 next_pc += sizeof(struct binary_op);
361 PO;
362 }
363 OP(FILTER_OP_LT_STRING):
364 {
365 int res;
366
367 res = (stack_strcmp(stack, top, "<") < 0);
368 estack_pop(stack, top, ax, bx);
369 estack_ax_v = res;
370 next_pc += sizeof(struct binary_op);
371 PO;
372 }
373 OP(FILTER_OP_GE_STRING):
374 {
375 int res;
376
377 res = (stack_strcmp(stack, top, ">=") >= 0);
378 estack_pop(stack, top, ax, bx);
379 estack_ax_v = res;
380 next_pc += sizeof(struct binary_op);
381 PO;
382 }
383 OP(FILTER_OP_LE_STRING):
384 {
385 int res;
386
387 res = (stack_strcmp(stack, top, "<=") <= 0);
388 estack_pop(stack, top, ax, bx);
389 estack_ax_v = res;
390 next_pc += sizeof(struct binary_op);
391 PO;
392 }
393
394 OP(FILTER_OP_EQ_S64):
395 {
396 int res;
397
398 res = (estack_bx_v == estack_ax_v);
399 estack_pop(stack, top, ax, bx);
400 estack_ax_v = res;
401 next_pc += sizeof(struct binary_op);
402 PO;
403 }
404 OP(FILTER_OP_NE_S64):
405 {
406 int res;
407
408 res = (estack_bx_v != estack_ax_v);
409 estack_pop(stack, top, ax, bx);
410 estack_ax_v = res;
411 next_pc += sizeof(struct binary_op);
412 PO;
413 }
414 OP(FILTER_OP_GT_S64):
415 {
416 int res;
417
418 res = (estack_bx_v > estack_ax_v);
419 estack_pop(stack, top, ax, bx);
420 estack_ax_v = res;
421 next_pc += sizeof(struct binary_op);
422 PO;
423 }
424 OP(FILTER_OP_LT_S64):
425 {
426 int res;
427
428 res = (estack_bx_v < estack_ax_v);
429 estack_pop(stack, top, ax, bx);
430 estack_ax_v = res;
431 next_pc += sizeof(struct binary_op);
432 PO;
433 }
434 OP(FILTER_OP_GE_S64):
435 {
436 int res;
437
438 res = (estack_bx_v >= estack_ax_v);
439 estack_pop(stack, top, ax, bx);
440 estack_ax_v = res;
441 next_pc += sizeof(struct binary_op);
442 PO;
443 }
444 OP(FILTER_OP_LE_S64):
445 {
446 int res;
447
448 res = (estack_bx_v <= estack_ax_v);
449 estack_pop(stack, top, ax, bx);
450 estack_ax_v = res;
451 next_pc += sizeof(struct binary_op);
452 PO;
453 }
454
455 OP(FILTER_OP_EQ_DOUBLE):
456 {
457 int res;
458
459 res = (estack_bx(stack, top)->u.d == estack_ax(stack, top)->u.d);
460 estack_pop(stack, top, ax, bx);
461 estack_ax_v = res;
462 next_pc += sizeof(struct binary_op);
463 PO;
464 }
465 OP(FILTER_OP_NE_DOUBLE):
466 {
467 int res;
468
469 res = (estack_bx(stack, top)->u.d != estack_ax(stack, top)->u.d);
470 estack_pop(stack, top, ax, bx);
471 estack_ax_v = res;
472 next_pc += sizeof(struct binary_op);
473 PO;
474 }
475 OP(FILTER_OP_GT_DOUBLE):
476 {
477 int res;
478
479 res = (estack_bx(stack, top)->u.d > estack_ax(stack, top)->u.d);
480 estack_pop(stack, top, ax, bx);
481 estack_ax_v = res;
482 next_pc += sizeof(struct binary_op);
483 PO;
484 }
485 OP(FILTER_OP_LT_DOUBLE):
486 {
487 int res;
488
489 res = (estack_bx(stack, top)->u.d < estack_ax(stack, top)->u.d);
490 estack_pop(stack, top, ax, bx);
491 estack_ax_v = res;
492 next_pc += sizeof(struct binary_op);
493 PO;
494 }
495 OP(FILTER_OP_GE_DOUBLE):
496 {
497 int res;
498
499 res = (estack_bx(stack, top)->u.d >= estack_ax(stack, top)->u.d);
500 estack_pop(stack, top, ax, bx);
501 estack_ax_v = res;
502 next_pc += sizeof(struct binary_op);
503 PO;
504 }
505 OP(FILTER_OP_LE_DOUBLE):
506 {
507 int res;
508
509 res = (estack_bx(stack, top)->u.d <= estack_ax(stack, top)->u.d);
510 estack_pop(stack, top, ax, bx);
511 estack_ax_v = res;
512 next_pc += sizeof(struct binary_op);
513 PO;
514 }
515
516 /* Mixed S64-double binary comparators */
517 OP(FILTER_OP_EQ_DOUBLE_S64):
518 {
519 int res;
520
521 res = (estack_bx(stack, top)->u.d == estack_ax_v);
522 estack_pop(stack, top, ax, bx);
523 estack_ax_v = res;
524 next_pc += sizeof(struct binary_op);
525 PO;
526 }
527 OP(FILTER_OP_NE_DOUBLE_S64):
528 {
529 int res;
530
531 res = (estack_bx(stack, top)->u.d != estack_ax_v);
532 estack_pop(stack, top, ax, bx);
533 estack_ax_v = res;
534 next_pc += sizeof(struct binary_op);
535 PO;
536 }
537 OP(FILTER_OP_GT_DOUBLE_S64):
538 {
539 int res;
540
541 res = (estack_bx(stack, top)->u.d > estack_ax_v);
542 estack_pop(stack, top, ax, bx);
543 estack_ax_v = res;
544 next_pc += sizeof(struct binary_op);
545 PO;
546 }
547 OP(FILTER_OP_LT_DOUBLE_S64):
548 {
549 int res;
550
551 res = (estack_bx(stack, top)->u.d < estack_ax_v);
552 estack_pop(stack, top, ax, bx);
553 estack_ax_v = res;
554 next_pc += sizeof(struct binary_op);
555 PO;
556 }
557 OP(FILTER_OP_GE_DOUBLE_S64):
558 {
559 int res;
560
561 res = (estack_bx(stack, top)->u.d >= estack_ax_v);
562 estack_pop(stack, top, ax, bx);
563 estack_ax_v = res;
564 next_pc += sizeof(struct binary_op);
565 PO;
566 }
567 OP(FILTER_OP_LE_DOUBLE_S64):
568 {
569 int res;
570
571 res = (estack_bx(stack, top)->u.d <= estack_ax_v);
572 estack_pop(stack, top, ax, bx);
573 estack_ax_v = res;
574 next_pc += sizeof(struct binary_op);
575 PO;
576 }
577
578 OP(FILTER_OP_EQ_S64_DOUBLE):
579 {
580 int res;
581
582 res = (estack_bx_v == estack_ax(stack, top)->u.d);
583 estack_pop(stack, top, ax, bx);
584 estack_ax_v = res;
585 next_pc += sizeof(struct binary_op);
586 PO;
587 }
588 OP(FILTER_OP_NE_S64_DOUBLE):
589 {
590 int res;
591
592 res = (estack_bx_v != estack_ax(stack, top)->u.d);
593 estack_pop(stack, top, ax, bx);
594 estack_ax_v = res;
595 next_pc += sizeof(struct binary_op);
596 PO;
597 }
598 OP(FILTER_OP_GT_S64_DOUBLE):
599 {
600 int res;
601
602 res = (estack_bx_v > estack_ax(stack, top)->u.d);
603 estack_pop(stack, top, ax, bx);
604 estack_ax_v = res;
605 next_pc += sizeof(struct binary_op);
606 PO;
607 }
608 OP(FILTER_OP_LT_S64_DOUBLE):
609 {
610 int res;
611
612 res = (estack_bx_v < estack_ax(stack, top)->u.d);
613 estack_pop(stack, top, ax, bx);
614 estack_ax_v = res;
615 next_pc += sizeof(struct binary_op);
616 PO;
617 }
618 OP(FILTER_OP_GE_S64_DOUBLE):
619 {
620 int res;
621
622 res = (estack_bx_v >= estack_ax(stack, top)->u.d);
623 estack_pop(stack, top, ax, bx);
624 estack_ax_v = res;
625 next_pc += sizeof(struct binary_op);
626 PO;
627 }
628 OP(FILTER_OP_LE_S64_DOUBLE):
629 {
630 int res;
631
632 res = (estack_bx_v <= estack_ax(stack, top)->u.d);
633 estack_pop(stack, top, ax, bx);
634 estack_ax_v = res;
635 next_pc += sizeof(struct binary_op);
636 PO;
637 }
638
639 /* unary */
640 OP(FILTER_OP_UNARY_PLUS):
641 OP(FILTER_OP_UNARY_MINUS):
642 OP(FILTER_OP_UNARY_NOT):
643 ERR("unsupported non-specialized bytecode op %u\n",
644 (unsigned int) *(filter_opcode_t *) pc);
645 ret = -EINVAL;
646 goto end;
647
648
649 OP(FILTER_OP_UNARY_PLUS_S64):
650 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
651 {
652 next_pc += sizeof(struct unary_op);
653 PO;
654 }
655 OP(FILTER_OP_UNARY_MINUS_S64):
656 {
657 estack_ax_v = -estack_ax_v;
658 next_pc += sizeof(struct unary_op);
659 PO;
660 }
661 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
662 {
663 estack_ax(stack, top)->u.d = -estack_ax(stack, top)->u.d;
664 next_pc += sizeof(struct unary_op);
665 PO;
666 }
667 OP(FILTER_OP_UNARY_NOT_S64):
668 {
669 estack_ax_v = !estack_ax_v;
670 next_pc += sizeof(struct unary_op);
671 PO;
672 }
673 OP(FILTER_OP_UNARY_NOT_DOUBLE):
674 {
675 estack_ax(stack, top)->u.d = !estack_ax(stack, top)->u.d;
676 next_pc += sizeof(struct unary_op);
677 PO;
678 }
679
680 /* logical */
681 OP(FILTER_OP_AND):
682 {
683 struct logical_op *insn = (struct logical_op *) pc;
684
685 /* If AX is 0, skip and evaluate to 0 */
686 if (unlikely(estack_ax_v == 0)) {
687 dbg_printf("Jumping to bytecode offset %u\n",
688 (unsigned int) insn->skip_offset);
689 next_pc = start_pc + insn->skip_offset;
690 } else {
691 /* Pop 1 when jump not taken */
692 estack_pop(stack, top, ax, bx);
693 next_pc += sizeof(struct logical_op);
694 }
695 PO;
696 }
697 OP(FILTER_OP_OR):
698 {
699 struct logical_op *insn = (struct logical_op *) pc;
700
701 /* If AX is nonzero, skip and evaluate to 1 */
702
703 if (unlikely(estack_ax_v != 0)) {
704 estack_ax_v = 1;
705 dbg_printf("Jumping to bytecode offset %u\n",
706 (unsigned int) insn->skip_offset);
707 next_pc = start_pc + insn->skip_offset;
708 } else {
709 /* Pop 1 when jump not taken */
710 estack_pop(stack, top, ax, bx);
711 next_pc += sizeof(struct logical_op);
712 }
713 PO;
714 }
715
716
717 /* load field ref */
718 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
719 {
720 struct load_op *insn = (struct load_op *) pc;
721 struct field_ref *ref = (struct field_ref *) insn->data;
722
723 dbg_printf("load field ref offset %u type string\n",
724 ref->offset);
725 estack_push(stack, top, ax, bx);
726 estack_ax(stack, top)->u.s.str =
727 *(const char * const *) &filter_stack_data[ref->offset];
728 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
729 dbg_printf("Filter warning: loading a NULL string.\n");
730 ret = -EINVAL;
731 goto end;
732 }
733 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
734 estack_ax(stack, top)->u.s.literal = 0;
735 dbg_printf("ref load string %s\n", estack_ax(stack, top)->u.s.str);
736 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
737 PO;
738 }
739
740 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
741 {
742 struct load_op *insn = (struct load_op *) pc;
743 struct field_ref *ref = (struct field_ref *) insn->data;
744
745 dbg_printf("load field ref offset %u type sequence\n",
746 ref->offset);
747 estack_push(stack, top, ax, bx);
748 estack_ax(stack, top)->u.s.seq_len =
749 *(unsigned long *) &filter_stack_data[ref->offset];
750 estack_ax(stack, top)->u.s.str =
751 *(const char **) (&filter_stack_data[ref->offset
752 + sizeof(unsigned long)]);
753 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
754 dbg_printf("Filter warning: loading a NULL sequence.\n");
755 ret = -EINVAL;
756 goto end;
757 }
758 estack_ax(stack, top)->u.s.literal = 0;
759 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
760 PO;
761 }
762
763 OP(FILTER_OP_LOAD_FIELD_REF_S64):
764 {
765 struct load_op *insn = (struct load_op *) pc;
766 struct field_ref *ref = (struct field_ref *) insn->data;
767
768 dbg_printf("load field ref offset %u type s64\n",
769 ref->offset);
770 estack_push(stack, top, ax, bx);
771 estack_ax_v =
772 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
773 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax_v);
774 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
775 PO;
776 }
777
778 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
779 {
780 struct load_op *insn = (struct load_op *) pc;
781 struct field_ref *ref = (struct field_ref *) insn->data;
782
783 dbg_printf("load field ref offset %u type double\n",
784 ref->offset);
785 estack_push(stack, top, ax, bx);
786 memcpy(&estack_ax(stack, top)->u.d, &filter_stack_data[ref->offset],
787 sizeof(struct literal_double));
788 dbg_printf("ref load double %g\n", estack_ax(stack, top)->u.d);
789 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
790 PO;
791 }
792
793 /* load from immediate operand */
794 OP(FILTER_OP_LOAD_STRING):
795 {
796 struct load_op *insn = (struct load_op *) pc;
797
798 dbg_printf("load string %s\n", insn->data);
799 estack_push(stack, top, ax, bx);
800 estack_ax(stack, top)->u.s.str = insn->data;
801 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
802 estack_ax(stack, top)->u.s.literal = 1;
803 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
804 PO;
805 }
806
807 OP(FILTER_OP_LOAD_S64):
808 {
809 struct load_op *insn = (struct load_op *) pc;
810
811 estack_push(stack, top, ax, bx);
812 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
813 dbg_printf("load s64 %" PRIi64 "\n", estack_ax_v);
814 next_pc += sizeof(struct load_op)
815 + sizeof(struct literal_numeric);
816 PO;
817 }
818
819 OP(FILTER_OP_LOAD_DOUBLE):
820 {
821 struct load_op *insn = (struct load_op *) pc;
822
823 estack_push(stack, top, ax, bx);
824 memcpy(&estack_ax(stack, top)->u.d, insn->data,
825 sizeof(struct literal_double));
826 dbg_printf("load s64 %g\n", estack_ax(stack, top)->u.d);
827 next_pc += sizeof(struct load_op)
828 + sizeof(struct literal_double);
829 PO;
830 }
831
832 /* cast */
833 OP(FILTER_OP_CAST_TO_S64):
834 ERR("unsupported non-specialized bytecode op %u\n",
835 (unsigned int) *(filter_opcode_t *) pc);
836 ret = -EINVAL;
837 goto end;
838
839 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
840 {
841 estack_ax_v = (int64_t) estack_ax(stack, top)->u.d;
842 next_pc += sizeof(struct cast_op);
843 PO;
844 }
845
846 OP(FILTER_OP_CAST_NOP):
847 {
848 next_pc += sizeof(struct cast_op);
849 PO;
850 }
851
852 /* get context ref */
853 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
854 {
855 struct load_op *insn = (struct load_op *) pc;
856 struct field_ref *ref = (struct field_ref *) insn->data;
857 struct lttng_ctx_field *ctx_field;
858 union lttng_ctx_value v;
859
860 dbg_printf("get context ref offset %u type string\n",
861 ref->offset);
862 ctx_field = &lttng_static_ctx->fields[ref->offset];
863 ctx_field->get_value(ctx_field, &v);
864 estack_push(stack, top, ax, bx);
865 estack_ax(stack, top)->u.s.str = v.str;
866 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
867 dbg_printf("Filter warning: loading a NULL string.\n");
868 ret = -EINVAL;
869 goto end;
870 }
871 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
872 estack_ax(stack, top)->u.s.literal = 0;
873 dbg_printf("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
874 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
875 PO;
876 }
877
878 OP(FILTER_OP_GET_CONTEXT_REF_S64):
879 {
880 struct load_op *insn = (struct load_op *) pc;
881 struct field_ref *ref = (struct field_ref *) insn->data;
882 struct lttng_ctx_field *ctx_field;
883 union lttng_ctx_value v;
884
885 dbg_printf("get context ref offset %u type s64\n",
886 ref->offset);
887 ctx_field = &lttng_static_ctx->fields[ref->offset];
888 ctx_field->get_value(ctx_field, &v);
889 estack_push(stack, top, ax, bx);
890 estack_ax_v = v.s64;
891 dbg_printf("ref get context s64 %" PRIi64 "\n", estack_ax_v);
892 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
893 PO;
894 }
895
896 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
897 {
898 struct load_op *insn = (struct load_op *) pc;
899 struct field_ref *ref = (struct field_ref *) insn->data;
900 struct lttng_ctx_field *ctx_field;
901 union lttng_ctx_value v;
902
903 dbg_printf("get context ref offset %u type double\n",
904 ref->offset);
905 ctx_field = &lttng_static_ctx->fields[ref->offset];
906 ctx_field->get_value(ctx_field, &v);
907 estack_push(stack, top, ax, bx);
908 memcpy(&estack_ax(stack, top)->u.d, &v.d, sizeof(struct literal_double));
909 dbg_printf("ref get context double %g\n", estack_ax(stack, top)->u.d);
910 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
911 PO;
912 }
913
914 END_OP
915 end:
916 /* return 0 (discard) on error */
917 if (ret)
918 return 0;
919 return retval;
920 }
921
922 #undef START_OP
923 #undef OP
924 #undef PO
925 #undef END_OP
This page took 0.047659 seconds and 4 git commands to generate.