Fix: filter linking can dereference NULL pointer on alloc failure
[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
8a92ed2a 108uint64_t lttng_filter_false(void *filter_data,
97b58163
MD
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
8a92ed2a
MD
160/*
161 * Return 0 (discard), or raise the 0x1 flag (log event).
162 * Currently, other flags are kept for future extensions and have no
163 * effect.
164 */
165uint64_t lttng_filter_interpret_bytecode(void *filter_data,
97b58163
MD
166 const char *filter_stack_data)
167{
168 struct bytecode_runtime *bytecode = filter_data;
169 void *pc, *next_pc, *start_pc;
170 int ret = -EINVAL;
171 int retval = 0;
0305960f
MD
172 struct estack _stack;
173 struct estack *stack = &_stack;
9b33aac4
MD
174 register int64_t ax = 0, bx = 0;
175 register int top = FILTER_STACK_EMPTY;
97b58163
MD
176#ifndef INTERPRETER_USE_SWITCH
177 static void *dispatch[NR_FILTER_OPS] = {
178 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
179
180 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
181
182 /* binary */
183 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
184 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
185 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
186 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
187 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
188 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
189 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
190 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
191 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
192 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
193
194 /* binary comparators */
195 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
196 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
197 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
198 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
199 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
200 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
201
202 /* string binary comparator */
203 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
204 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
205 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
206 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
207 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
208 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
209
210 /* s64 binary comparator */
211 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
212 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
213 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
214 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
215 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
216 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
217
218 /* double binary comparator */
219 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
220 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
221 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
222 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
223 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
224 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
225
dbea82ec
MD
226 /* Mixed S64-double binary comparators */
227 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
228 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
229 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
230 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
231 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
232 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
233
234 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
235 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
236 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
237 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
238 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
239 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
240
97b58163
MD
241 /* unary */
242 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
243 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
244 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
245 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
246 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
247 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
248 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
249 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
250 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
251
252 /* logical */
253 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
254 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
255
256 /* load */
257 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
258 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
259 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
260 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
261 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
262
263 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
264 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
265 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
266
267 /* cast */
268 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
269 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
270 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
271 };
272#endif /* #ifndef INTERPRETER_USE_SWITCH */
273
274 START_OP
275
276 OP(FILTER_OP_UNKNOWN):
277 OP(FILTER_OP_LOAD_FIELD_REF):
278#ifdef INTERPRETER_USE_SWITCH
279 default:
280#endif /* INTERPRETER_USE_SWITCH */
281 ERR("unknown bytecode op %u\n",
282 (unsigned int) *(filter_opcode_t *) pc);
283 ret = -EINVAL;
284 goto end;
285
286 OP(FILTER_OP_RETURN):
8a92ed2a 287 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
9b33aac4 288 retval = !!estack_ax_v;
97b58163
MD
289 ret = 0;
290 goto end;
291
292 /* binary */
293 OP(FILTER_OP_MUL):
294 OP(FILTER_OP_DIV):
295 OP(FILTER_OP_MOD):
296 OP(FILTER_OP_PLUS):
297 OP(FILTER_OP_MINUS):
298 OP(FILTER_OP_RSHIFT):
299 OP(FILTER_OP_LSHIFT):
300 OP(FILTER_OP_BIN_AND):
301 OP(FILTER_OP_BIN_OR):
302 OP(FILTER_OP_BIN_XOR):
303 ERR("unsupported bytecode op %u\n",
304 (unsigned int) *(filter_opcode_t *) pc);
305 ret = -EINVAL;
306 goto end;
307
308 OP(FILTER_OP_EQ):
309 OP(FILTER_OP_NE):
310 OP(FILTER_OP_GT):
311 OP(FILTER_OP_LT):
312 OP(FILTER_OP_GE):
313 OP(FILTER_OP_LE):
314 ERR("unsupported non-specialized bytecode op %u\n",
315 (unsigned int) *(filter_opcode_t *) pc);
316 ret = -EINVAL;
317 goto end;
318
319 OP(FILTER_OP_EQ_STRING):
320 {
0305960f
MD
321 int res;
322
9b33aac4
MD
323 res = (stack_strcmp(stack, top, "==") == 0);
324 estack_pop(stack, top, ax, bx);
325 estack_ax_v = res;
97b58163
MD
326 next_pc += sizeof(struct binary_op);
327 PO;
328 }
329 OP(FILTER_OP_NE_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_GT_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_LT_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_GE_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_LE_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
380 OP(FILTER_OP_EQ_S64):
381 {
0305960f
MD
382 int res;
383
9b33aac4
MD
384 res = (estack_bx_v == estack_ax_v);
385 estack_pop(stack, top, ax, bx);
386 estack_ax_v = res;
97b58163
MD
387 next_pc += sizeof(struct binary_op);
388 PO;
389 }
390 OP(FILTER_OP_NE_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_GT_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_LT_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_GE_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_LE_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
441 OP(FILTER_OP_EQ_DOUBLE):
442 {
0305960f
MD
443 int res;
444
9b33aac4
MD
445 res = (estack_bx(stack, top)->u.d == estack_ax(stack, top)->u.d);
446 estack_pop(stack, top, ax, bx);
447 estack_ax_v = res;
97b58163
MD
448 next_pc += sizeof(struct binary_op);
449 PO;
450 }
451 OP(FILTER_OP_NE_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_GT_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_LT_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_GE_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_LE_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;
dbea82ec
MD
498 next_pc += sizeof(struct binary_op);
499 PO;
500 }
501
502 /* Mixed S64-double binary comparators */
503 OP(FILTER_OP_EQ_DOUBLE_S64):
504 {
505 int res;
506
9b33aac4
MD
507 res = (estack_bx(stack, top)->u.d == estack_ax_v);
508 estack_pop(stack, top, ax, bx);
509 estack_ax_v = res;
dbea82ec
MD
510 next_pc += sizeof(struct binary_op);
511 PO;
512 }
513 OP(FILTER_OP_NE_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_GT_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_LT_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_GE_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_LE_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
564 OP(FILTER_OP_EQ_S64_DOUBLE):
565 {
566 int res;
567
9b33aac4
MD
568 res = (estack_bx_v == estack_ax(stack, top)->u.d);
569 estack_pop(stack, top, ax, bx);
570 estack_ax_v = res;
dbea82ec
MD
571 next_pc += sizeof(struct binary_op);
572 PO;
573 }
574 OP(FILTER_OP_NE_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_GT_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_LT_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_GE_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_LE_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;
97b58163
MD
621 next_pc += sizeof(struct binary_op);
622 PO;
623 }
624
625 /* unary */
626 OP(FILTER_OP_UNARY_PLUS):
627 OP(FILTER_OP_UNARY_MINUS):
628 OP(FILTER_OP_UNARY_NOT):
629 ERR("unsupported non-specialized bytecode op %u\n",
630 (unsigned int) *(filter_opcode_t *) pc);
631 ret = -EINVAL;
632 goto end;
633
634
635 OP(FILTER_OP_UNARY_PLUS_S64):
636 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
637 {
638 next_pc += sizeof(struct unary_op);
639 PO;
640 }
641 OP(FILTER_OP_UNARY_MINUS_S64):
642 {
9b33aac4 643 estack_ax_v = -estack_ax_v;
97b58163
MD
644 next_pc += sizeof(struct unary_op);
645 PO;
646 }
647 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
648 {
9b33aac4 649 estack_ax(stack, top)->u.d = -estack_ax(stack, top)->u.d;
97b58163
MD
650 next_pc += sizeof(struct unary_op);
651 PO;
652 }
653 OP(FILTER_OP_UNARY_NOT_S64):
654 {
9b33aac4 655 estack_ax_v = !estack_ax_v;
97b58163
MD
656 next_pc += sizeof(struct unary_op);
657 PO;
658 }
659 OP(FILTER_OP_UNARY_NOT_DOUBLE):
660 {
9b33aac4 661 estack_ax(stack, top)->u.d = !estack_ax(stack, top)->u.d;
97b58163
MD
662 next_pc += sizeof(struct unary_op);
663 PO;
664 }
665
666 /* logical */
667 OP(FILTER_OP_AND):
668 {
669 struct logical_op *insn = (struct logical_op *) pc;
670
0305960f 671 /* If AX is 0, skip and evaluate to 0 */
9b33aac4 672 if (unlikely(estack_ax_v == 0)) {
97b58163
MD
673 dbg_printf("Jumping to bytecode offset %u\n",
674 (unsigned int) insn->skip_offset);
675 next_pc = start_pc + insn->skip_offset;
676 } else {
71c1ceeb 677 /* Pop 1 when jump not taken */
9b33aac4 678 estack_pop(stack, top, ax, bx);
97b58163
MD
679 next_pc += sizeof(struct logical_op);
680 }
681 PO;
682 }
683 OP(FILTER_OP_OR):
684 {
685 struct logical_op *insn = (struct logical_op *) pc;
686
0305960f 687 /* If AX is nonzero, skip and evaluate to 1 */
97b58163 688
9b33aac4
MD
689 if (unlikely(estack_ax_v != 0)) {
690 estack_ax_v = 1;
97b58163
MD
691 dbg_printf("Jumping to bytecode offset %u\n",
692 (unsigned int) insn->skip_offset);
693 next_pc = start_pc + insn->skip_offset;
694 } else {
71c1ceeb 695 /* Pop 1 when jump not taken */
9b33aac4 696 estack_pop(stack, top, ax, bx);
97b58163
MD
697 next_pc += sizeof(struct logical_op);
698 }
699 PO;
700 }
701
702
703 /* load */
704 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
705 {
706 struct load_op *insn = (struct load_op *) pc;
707 struct field_ref *ref = (struct field_ref *) insn->data;
708
709 dbg_printf("load field ref offset %u type string\n",
710 ref->offset);
9b33aac4
MD
711 estack_push(stack, top, ax, bx);
712 estack_ax(stack, top)->u.s.str =
97b58163 713 *(const char * const *) &filter_stack_data[ref->offset];
9b33aac4 714 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
97b58163
MD
715 dbg_printf("Filter warning: loading a NULL string.\n");
716 ret = -EINVAL;
717 goto end;
718 }
9b33aac4
MD
719 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
720 estack_ax(stack, top)->u.s.literal = 0;
721 dbg_printf("ref load string %s\n", estack_ax(stack, top)->u.s.str);
97b58163
MD
722 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
723 PO;
724 }
725
726 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
727 {
728 struct load_op *insn = (struct load_op *) pc;
729 struct field_ref *ref = (struct field_ref *) insn->data;
730
731 dbg_printf("load field ref offset %u type sequence\n",
732 ref->offset);
9b33aac4
MD
733 estack_push(stack, top, ax, bx);
734 estack_ax(stack, top)->u.s.seq_len =
97b58163 735 *(unsigned long *) &filter_stack_data[ref->offset];
9b33aac4 736 estack_ax(stack, top)->u.s.str =
97b58163
MD
737 *(const char **) (&filter_stack_data[ref->offset
738 + sizeof(unsigned long)]);
9b33aac4 739 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
97b58163
MD
740 dbg_printf("Filter warning: loading a NULL sequence.\n");
741 ret = -EINVAL;
742 goto end;
743 }
9b33aac4 744 estack_ax(stack, top)->u.s.literal = 0;
97b58163
MD
745 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
746 PO;
747 }
748
749 OP(FILTER_OP_LOAD_FIELD_REF_S64):
750 {
751 struct load_op *insn = (struct load_op *) pc;
752 struct field_ref *ref = (struct field_ref *) insn->data;
753
754 dbg_printf("load field ref offset %u type s64\n",
755 ref->offset);
9b33aac4
MD
756 estack_push(stack, top, ax, bx);
757 estack_ax_v =
758 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
759 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax_v);
97b58163
MD
760 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
761 PO;
762 }
763
764 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
765 {
766 struct load_op *insn = (struct load_op *) pc;
767 struct field_ref *ref = (struct field_ref *) insn->data;
768
769 dbg_printf("load field ref offset %u type double\n",
770 ref->offset);
9b33aac4
MD
771 estack_push(stack, top, ax, bx);
772 memcpy(&estack_ax(stack, top)->u.d, &filter_stack_data[ref->offset],
97b58163 773 sizeof(struct literal_double));
9b33aac4 774 dbg_printf("ref load double %g\n", estack_ax(stack, top)->u.d);
97b58163
MD
775 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
776 PO;
777 }
778
779 OP(FILTER_OP_LOAD_STRING):
780 {
781 struct load_op *insn = (struct load_op *) pc;
782
783 dbg_printf("load string %s\n", insn->data);
9b33aac4
MD
784 estack_push(stack, top, ax, bx);
785 estack_ax(stack, top)->u.s.str = insn->data;
786 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
787 estack_ax(stack, top)->u.s.literal = 1;
97b58163
MD
788 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
789 PO;
790 }
791
792 OP(FILTER_OP_LOAD_S64):
793 {
794 struct load_op *insn = (struct load_op *) pc;
795
9b33aac4
MD
796 estack_push(stack, top, ax, bx);
797 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
798 dbg_printf("load s64 %" PRIi64 "\n", estack_ax_v);
97b58163
MD
799 next_pc += sizeof(struct load_op)
800 + sizeof(struct literal_numeric);
801 PO;
802 }
803
804 OP(FILTER_OP_LOAD_DOUBLE):
805 {
806 struct load_op *insn = (struct load_op *) pc;
807
9b33aac4
MD
808 estack_push(stack, top, ax, bx);
809 memcpy(&estack_ax(stack, top)->u.d, insn->data,
97b58163 810 sizeof(struct literal_double));
9b33aac4 811 dbg_printf("load s64 %g\n", estack_ax(stack, top)->u.d);
97b58163
MD
812 next_pc += sizeof(struct load_op)
813 + sizeof(struct literal_double);
814 PO;
815 }
816
817 /* cast */
818 OP(FILTER_OP_CAST_TO_S64):
819 ERR("unsupported non-specialized bytecode op %u\n",
820 (unsigned int) *(filter_opcode_t *) pc);
821 ret = -EINVAL;
822 goto end;
823
824 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
825 {
9b33aac4 826 estack_ax_v = (int64_t) estack_ax(stack, top)->u.d;
97b58163
MD
827 next_pc += sizeof(struct cast_op);
828 PO;
829 }
830
831 OP(FILTER_OP_CAST_NOP):
832 {
833 next_pc += sizeof(struct cast_op);
834 PO;
835 }
836
837 END_OP
838end:
839 /* return 0 (discard) on error */
840 if (ret)
841 return 0;
842 return retval;
843}
844
845#undef START_OP
846#undef OP
847#undef PO
848#undef END_OP
This page took 0.057922 seconds and 4 git commands to generate.