~ubuntu-branches/ubuntu/wily/ust/wily-proposed

« back to all changes in this revision

Viewing changes to liblttng-ust/lttng-filter-interpreter.c

  • Committer: Package Import Robot
  • Author(s): Jon Bernard
  • Date: 2012-09-11 15:34:43 UTC
  • mto: (11.2.1 sid) (1.2.1)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20120911153443-2rqyy0ewazyl4rp0
Tags: upstream-2.1.0~rc1
ImportĀ upstreamĀ versionĀ 2.1.0~rc1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
                                diff = 0;
 
64
                        else
 
65
                                diff = -1;
 
66
                        break;
 
67
                }
 
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')
 
70
                                diff = 0;
 
71
                        else
 
72
                                diff = 1;
 
73
                        break;
 
74
                }
 
75
                if (estack_bx(stack, top)->u.s.literal) {
 
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
                }
 
84
                if (estack_ax(stack, top)->u.s.literal) {
 
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
 
 
108
int 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)                                                        \
 
150
LABEL_##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
 
 
160
int 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;
 
167
        struct estack _stack;
 
168
        struct estack *stack = &_stack;
 
169
        register int64_t ax = 0, bx = 0;
 
170
        register int top = FILTER_STACK_EMPTY;
 
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
 
 
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
 
 
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):
 
282
                        retval = !!estack_ax_v;
 
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
                {
 
315
                        int res;
 
316
 
 
317
                        res = (stack_strcmp(stack, top, "==") == 0);
 
318
                        estack_pop(stack, top, ax, bx);
 
319
                        estack_ax_v = res;
 
320
                        next_pc += sizeof(struct binary_op);
 
321
                        PO;
 
322
                }
 
323
                OP(FILTER_OP_NE_STRING):
 
324
                {
 
325
                        int res;
 
326
 
 
327
                        res = (stack_strcmp(stack, top, "!=") != 0);
 
328
                        estack_pop(stack, top, ax, bx);
 
329
                        estack_ax_v = res;
 
330
                        next_pc += sizeof(struct binary_op);
 
331
                        PO;
 
332
                }
 
333
                OP(FILTER_OP_GT_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_LT_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_GE_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_LE_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
 
 
374
                OP(FILTER_OP_EQ_S64):
 
375
                {
 
376
                        int res;
 
377
 
 
378
                        res = (estack_bx_v == estack_ax_v);
 
379
                        estack_pop(stack, top, ax, bx);
 
380
                        estack_ax_v = res;
 
381
                        next_pc += sizeof(struct binary_op);
 
382
                        PO;
 
383
                }
 
384
                OP(FILTER_OP_NE_S64):
 
385
                {
 
386
                        int res;
 
387
 
 
388
                        res = (estack_bx_v != estack_ax_v);
 
389
                        estack_pop(stack, top, ax, bx);
 
390
                        estack_ax_v = res;
 
391
                        next_pc += sizeof(struct binary_op);
 
392
                        PO;
 
393
                }
 
394
                OP(FILTER_OP_GT_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_LT_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_GE_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_LE_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
 
 
435
                OP(FILTER_OP_EQ_DOUBLE):
 
436
                {
 
437
                        int res;
 
438
 
 
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;
 
442
                        next_pc += sizeof(struct binary_op);
 
443
                        PO;
 
444
                }
 
445
                OP(FILTER_OP_NE_DOUBLE):
 
446
                {
 
447
                        int res;
 
448
 
 
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;
 
452
                        next_pc += sizeof(struct binary_op);
 
453
                        PO;
 
454
                }
 
455
                OP(FILTER_OP_GT_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_LT_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_GE_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_LE_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
 
 
496
                /* Mixed S64-double binary comparators */
 
497
                OP(FILTER_OP_EQ_DOUBLE_S64):
 
498
                {
 
499
                        int res;
 
500
 
 
501
                        res = (estack_bx(stack, top)->u.d == estack_ax_v);
 
502
                        estack_pop(stack, top, ax, bx);
 
503
                        estack_ax_v = res;
 
504
                        next_pc += sizeof(struct binary_op);
 
505
                        PO;
 
506
                }
 
507
                OP(FILTER_OP_NE_DOUBLE_S64):
 
508
                {
 
509
                        int res;
 
510
 
 
511
                        res = (estack_bx(stack, top)->u.d != estack_ax_v);
 
512
                        estack_pop(stack, top, ax, bx);
 
513
                        estack_ax_v = res;
 
514
                        next_pc += sizeof(struct binary_op);
 
515
                        PO;
 
516
                }
 
517
                OP(FILTER_OP_GT_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_LT_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_GE_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_LE_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
 
 
558
                OP(FILTER_OP_EQ_S64_DOUBLE):
 
559
                {
 
560
                        int res;
 
561
 
 
562
                        res = (estack_bx_v == estack_ax(stack, top)->u.d);
 
563
                        estack_pop(stack, top, ax, bx);
 
564
                        estack_ax_v = res;
 
565
                        next_pc += sizeof(struct binary_op);
 
566
                        PO;
 
567
                }
 
568
                OP(FILTER_OP_NE_S64_DOUBLE):
 
569
                {
 
570
                        int res;
 
571
 
 
572
                        res = (estack_bx_v != estack_ax(stack, top)->u.d);
 
573
                        estack_pop(stack, top, ax, bx);
 
574
                        estack_ax_v = res;
 
575
                        next_pc += sizeof(struct binary_op);
 
576
                        PO;
 
577
                }
 
578
                OP(FILTER_OP_GT_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_LT_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_GE_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_LE_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
 
 
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
                {
 
637
                        estack_ax_v = -estack_ax_v;
 
638
                        next_pc += sizeof(struct unary_op);
 
639
                        PO;
 
640
                }
 
641
                OP(FILTER_OP_UNARY_MINUS_DOUBLE):
 
642
                {
 
643
                        estack_ax(stack, top)->u.d = -estack_ax(stack, top)->u.d;
 
644
                        next_pc += sizeof(struct unary_op);
 
645
                        PO;
 
646
                }
 
647
                OP(FILTER_OP_UNARY_NOT_S64):
 
648
                {
 
649
                        estack_ax_v = !estack_ax_v;
 
650
                        next_pc += sizeof(struct unary_op);
 
651
                        PO;
 
652
                }
 
653
                OP(FILTER_OP_UNARY_NOT_DOUBLE):
 
654
                {
 
655
                        estack_ax(stack, top)->u.d = !estack_ax(stack, top)->u.d;
 
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
 
 
665
                        /* If AX is 0, skip and evaluate to 0 */
 
666
                        if (unlikely(estack_ax_v == 0)) {
 
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 {
 
671
                                /* Pop 1 when jump not taken */
 
672
                                estack_pop(stack, top, ax, bx);
 
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
 
 
681
                        /* If AX is nonzero, skip and evaluate to 1 */
 
682
 
 
683
                        if (unlikely(estack_ax_v != 0)) {
 
684
                                estack_ax_v = 1;
 
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 {
 
689
                                /* Pop 1 when jump not taken */
 
690
                                estack_pop(stack, top, ax, bx);
 
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);
 
705
                        estack_push(stack, top, ax, bx);
 
706
                        estack_ax(stack, top)->u.s.str =
 
707
                                *(const char * const *) &filter_stack_data[ref->offset];
 
708
                        if (unlikely(!estack_ax(stack, top)->u.s.str)) {
 
709
                                dbg_printf("Filter warning: loading a NULL string.\n");
 
710
                                ret = -EINVAL;
 
711
                                goto end;
 
712
                        }
 
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);
 
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);
 
727
                        estack_push(stack, top, ax, bx);
 
728
                        estack_ax(stack, top)->u.s.seq_len =
 
729
                                *(unsigned long *) &filter_stack_data[ref->offset];
 
730
                        estack_ax(stack, top)->u.s.str =
 
731
                                *(const char **) (&filter_stack_data[ref->offset
 
732
                                                                + sizeof(unsigned long)]);
 
733
                        if (unlikely(!estack_ax(stack, top)->u.s.str)) {
 
734
                                dbg_printf("Filter warning: loading a NULL sequence.\n");
 
735
                                ret = -EINVAL;
 
736
                                goto end;
 
737
                        }
 
738
                        estack_ax(stack, top)->u.s.literal = 0;
 
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);
 
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);
 
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);
 
765
                        estack_push(stack, top, ax, bx);
 
766
                        memcpy(&estack_ax(stack, top)->u.d, &filter_stack_data[ref->offset],
 
767
                                sizeof(struct literal_double));
 
768
                        dbg_printf("ref load double %g\n", estack_ax(stack, top)->u.d);
 
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);
 
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;
 
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
 
 
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);
 
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
 
 
802
                        estack_push(stack, top, ax, bx);
 
803
                        memcpy(&estack_ax(stack, top)->u.d, insn->data,
 
804
                                sizeof(struct literal_double));
 
805
                        dbg_printf("load s64 %g\n", estack_ax(stack, top)->u.d);
 
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
                {
 
820
                        estack_ax_v = (int64_t) estack_ax(stack, top)->u.d;
 
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
 
832
end:
 
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