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