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