Fix: off-by-one in sequence filter comparator
[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
35c7fa92
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') {
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 }
35c7fa92
MD
73 if (unlikely(q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0')) {
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
77aa5901 266 /* load field ref */
97b58163
MD
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
77aa5901 273 /* load from immediate operand */
97b58163
MD
274 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
275 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
276 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
277
278 /* cast */
279 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
280 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
281 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
77aa5901
MD
282
283 /* get context ref */
284 [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
285 [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
286 [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
287 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
97b58163
MD
288 };
289#endif /* #ifndef INTERPRETER_USE_SWITCH */
290
291 START_OP
292
293 OP(FILTER_OP_UNKNOWN):
294 OP(FILTER_OP_LOAD_FIELD_REF):
77aa5901 295 OP(FILTER_OP_GET_CONTEXT_REF):
97b58163
MD
296#ifdef INTERPRETER_USE_SWITCH
297 default:
298#endif /* INTERPRETER_USE_SWITCH */
299 ERR("unknown bytecode op %u\n",
300 (unsigned int) *(filter_opcode_t *) pc);
301 ret = -EINVAL;
302 goto end;
303
304 OP(FILTER_OP_RETURN):
8a92ed2a 305 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
9b33aac4 306 retval = !!estack_ax_v;
97b58163
MD
307 ret = 0;
308 goto end;
309
310 /* binary */
311 OP(FILTER_OP_MUL):
312 OP(FILTER_OP_DIV):
313 OP(FILTER_OP_MOD):
314 OP(FILTER_OP_PLUS):
315 OP(FILTER_OP_MINUS):
316 OP(FILTER_OP_RSHIFT):
317 OP(FILTER_OP_LSHIFT):
318 OP(FILTER_OP_BIN_AND):
319 OP(FILTER_OP_BIN_OR):
320 OP(FILTER_OP_BIN_XOR):
321 ERR("unsupported bytecode op %u\n",
322 (unsigned int) *(filter_opcode_t *) pc);
323 ret = -EINVAL;
324 goto end;
325
326 OP(FILTER_OP_EQ):
327 OP(FILTER_OP_NE):
328 OP(FILTER_OP_GT):
329 OP(FILTER_OP_LT):
330 OP(FILTER_OP_GE):
331 OP(FILTER_OP_LE):
332 ERR("unsupported non-specialized bytecode op %u\n",
333 (unsigned int) *(filter_opcode_t *) pc);
334 ret = -EINVAL;
335 goto end;
336
337 OP(FILTER_OP_EQ_STRING):
338 {
0305960f
MD
339 int res;
340
9b33aac4
MD
341 res = (stack_strcmp(stack, top, "==") == 0);
342 estack_pop(stack, top, ax, bx);
343 estack_ax_v = res;
97b58163
MD
344 next_pc += sizeof(struct binary_op);
345 PO;
346 }
347 OP(FILTER_OP_NE_STRING):
348 {
0305960f
MD
349 int res;
350
9b33aac4
MD
351 res = (stack_strcmp(stack, top, "!=") != 0);
352 estack_pop(stack, top, ax, bx);
353 estack_ax_v = res;
97b58163
MD
354 next_pc += sizeof(struct binary_op);
355 PO;
356 }
357 OP(FILTER_OP_GT_STRING):
358 {
0305960f
MD
359 int res;
360
9b33aac4
MD
361 res = (stack_strcmp(stack, top, ">") > 0);
362 estack_pop(stack, top, ax, bx);
363 estack_ax_v = res;
97b58163
MD
364 next_pc += sizeof(struct binary_op);
365 PO;
366 }
367 OP(FILTER_OP_LT_STRING):
368 {
0305960f
MD
369 int res;
370
9b33aac4
MD
371 res = (stack_strcmp(stack, top, "<") < 0);
372 estack_pop(stack, top, ax, bx);
373 estack_ax_v = res;
97b58163
MD
374 next_pc += sizeof(struct binary_op);
375 PO;
376 }
377 OP(FILTER_OP_GE_STRING):
378 {
0305960f
MD
379 int res;
380
9b33aac4
MD
381 res = (stack_strcmp(stack, top, ">=") >= 0);
382 estack_pop(stack, top, ax, bx);
383 estack_ax_v = res;
97b58163
MD
384 next_pc += sizeof(struct binary_op);
385 PO;
386 }
387 OP(FILTER_OP_LE_STRING):
388 {
0305960f
MD
389 int res;
390
9b33aac4
MD
391 res = (stack_strcmp(stack, top, "<=") <= 0);
392 estack_pop(stack, top, ax, bx);
393 estack_ax_v = res;
97b58163
MD
394 next_pc += sizeof(struct binary_op);
395 PO;
396 }
397
398 OP(FILTER_OP_EQ_S64):
399 {
0305960f
MD
400 int res;
401
9b33aac4
MD
402 res = (estack_bx_v == estack_ax_v);
403 estack_pop(stack, top, ax, bx);
404 estack_ax_v = res;
97b58163
MD
405 next_pc += sizeof(struct binary_op);
406 PO;
407 }
408 OP(FILTER_OP_NE_S64):
409 {
0305960f
MD
410 int res;
411
9b33aac4
MD
412 res = (estack_bx_v != estack_ax_v);
413 estack_pop(stack, top, ax, bx);
414 estack_ax_v = res;
97b58163
MD
415 next_pc += sizeof(struct binary_op);
416 PO;
417 }
418 OP(FILTER_OP_GT_S64):
419 {
0305960f
MD
420 int res;
421
9b33aac4
MD
422 res = (estack_bx_v > estack_ax_v);
423 estack_pop(stack, top, ax, bx);
424 estack_ax_v = res;
97b58163
MD
425 next_pc += sizeof(struct binary_op);
426 PO;
427 }
428 OP(FILTER_OP_LT_S64):
429 {
0305960f
MD
430 int res;
431
9b33aac4
MD
432 res = (estack_bx_v < estack_ax_v);
433 estack_pop(stack, top, ax, bx);
434 estack_ax_v = res;
97b58163
MD
435 next_pc += sizeof(struct binary_op);
436 PO;
437 }
438 OP(FILTER_OP_GE_S64):
439 {
0305960f
MD
440 int res;
441
9b33aac4
MD
442 res = (estack_bx_v >= estack_ax_v);
443 estack_pop(stack, top, ax, bx);
444 estack_ax_v = res;
97b58163
MD
445 next_pc += sizeof(struct binary_op);
446 PO;
447 }
448 OP(FILTER_OP_LE_S64):
449 {
0305960f
MD
450 int res;
451
9b33aac4
MD
452 res = (estack_bx_v <= estack_ax_v);
453 estack_pop(stack, top, ax, bx);
454 estack_ax_v = res;
97b58163
MD
455 next_pc += sizeof(struct binary_op);
456 PO;
457 }
458
459 OP(FILTER_OP_EQ_DOUBLE):
460 {
0305960f
MD
461 int res;
462
9b33aac4
MD
463 res = (estack_bx(stack, top)->u.d == estack_ax(stack, top)->u.d);
464 estack_pop(stack, top, ax, bx);
465 estack_ax_v = res;
97b58163
MD
466 next_pc += sizeof(struct binary_op);
467 PO;
468 }
469 OP(FILTER_OP_NE_DOUBLE):
470 {
0305960f
MD
471 int res;
472
9b33aac4
MD
473 res = (estack_bx(stack, top)->u.d != estack_ax(stack, top)->u.d);
474 estack_pop(stack, top, ax, bx);
475 estack_ax_v = res;
97b58163
MD
476 next_pc += sizeof(struct binary_op);
477 PO;
478 }
479 OP(FILTER_OP_GT_DOUBLE):
480 {
0305960f
MD
481 int res;
482
9b33aac4
MD
483 res = (estack_bx(stack, top)->u.d > estack_ax(stack, top)->u.d);
484 estack_pop(stack, top, ax, bx);
485 estack_ax_v = res;
97b58163
MD
486 next_pc += sizeof(struct binary_op);
487 PO;
488 }
489 OP(FILTER_OP_LT_DOUBLE):
490 {
0305960f
MD
491 int res;
492
9b33aac4
MD
493 res = (estack_bx(stack, top)->u.d < estack_ax(stack, top)->u.d);
494 estack_pop(stack, top, ax, bx);
495 estack_ax_v = res;
97b58163
MD
496 next_pc += sizeof(struct binary_op);
497 PO;
498 }
499 OP(FILTER_OP_GE_DOUBLE):
500 {
0305960f
MD
501 int res;
502
9b33aac4
MD
503 res = (estack_bx(stack, top)->u.d >= estack_ax(stack, top)->u.d);
504 estack_pop(stack, top, ax, bx);
505 estack_ax_v = res;
97b58163
MD
506 next_pc += sizeof(struct binary_op);
507 PO;
508 }
509 OP(FILTER_OP_LE_DOUBLE):
510 {
0305960f
MD
511 int res;
512
9b33aac4
MD
513 res = (estack_bx(stack, top)->u.d <= estack_ax(stack, top)->u.d);
514 estack_pop(stack, top, ax, bx);
515 estack_ax_v = res;
dbea82ec
MD
516 next_pc += sizeof(struct binary_op);
517 PO;
518 }
519
520 /* Mixed S64-double binary comparators */
521 OP(FILTER_OP_EQ_DOUBLE_S64):
522 {
523 int res;
524
9b33aac4
MD
525 res = (estack_bx(stack, top)->u.d == estack_ax_v);
526 estack_pop(stack, top, ax, bx);
527 estack_ax_v = res;
dbea82ec
MD
528 next_pc += sizeof(struct binary_op);
529 PO;
530 }
531 OP(FILTER_OP_NE_DOUBLE_S64):
532 {
533 int res;
534
9b33aac4
MD
535 res = (estack_bx(stack, top)->u.d != estack_ax_v);
536 estack_pop(stack, top, ax, bx);
537 estack_ax_v = res;
dbea82ec
MD
538 next_pc += sizeof(struct binary_op);
539 PO;
540 }
541 OP(FILTER_OP_GT_DOUBLE_S64):
542 {
543 int res;
544
9b33aac4
MD
545 res = (estack_bx(stack, top)->u.d > estack_ax_v);
546 estack_pop(stack, top, ax, bx);
547 estack_ax_v = res;
dbea82ec
MD
548 next_pc += sizeof(struct binary_op);
549 PO;
550 }
551 OP(FILTER_OP_LT_DOUBLE_S64):
552 {
553 int res;
554
9b33aac4
MD
555 res = (estack_bx(stack, top)->u.d < estack_ax_v);
556 estack_pop(stack, top, ax, bx);
557 estack_ax_v = res;
dbea82ec
MD
558 next_pc += sizeof(struct binary_op);
559 PO;
560 }
561 OP(FILTER_OP_GE_DOUBLE_S64):
562 {
563 int res;
564
9b33aac4
MD
565 res = (estack_bx(stack, top)->u.d >= estack_ax_v);
566 estack_pop(stack, top, ax, bx);
567 estack_ax_v = res;
dbea82ec
MD
568 next_pc += sizeof(struct binary_op);
569 PO;
570 }
571 OP(FILTER_OP_LE_DOUBLE_S64):
572 {
573 int res;
574
9b33aac4
MD
575 res = (estack_bx(stack, top)->u.d <= estack_ax_v);
576 estack_pop(stack, top, ax, bx);
577 estack_ax_v = res;
dbea82ec
MD
578 next_pc += sizeof(struct binary_op);
579 PO;
580 }
581
582 OP(FILTER_OP_EQ_S64_DOUBLE):
583 {
584 int res;
585
9b33aac4
MD
586 res = (estack_bx_v == estack_ax(stack, top)->u.d);
587 estack_pop(stack, top, ax, bx);
588 estack_ax_v = res;
dbea82ec
MD
589 next_pc += sizeof(struct binary_op);
590 PO;
591 }
592 OP(FILTER_OP_NE_S64_DOUBLE):
593 {
594 int res;
595
9b33aac4
MD
596 res = (estack_bx_v != estack_ax(stack, top)->u.d);
597 estack_pop(stack, top, ax, bx);
598 estack_ax_v = res;
dbea82ec
MD
599 next_pc += sizeof(struct binary_op);
600 PO;
601 }
602 OP(FILTER_OP_GT_S64_DOUBLE):
603 {
604 int res;
605
9b33aac4
MD
606 res = (estack_bx_v > estack_ax(stack, top)->u.d);
607 estack_pop(stack, top, ax, bx);
608 estack_ax_v = res;
dbea82ec
MD
609 next_pc += sizeof(struct binary_op);
610 PO;
611 }
612 OP(FILTER_OP_LT_S64_DOUBLE):
613 {
614 int res;
615
9b33aac4
MD
616 res = (estack_bx_v < estack_ax(stack, top)->u.d);
617 estack_pop(stack, top, ax, bx);
618 estack_ax_v = res;
dbea82ec
MD
619 next_pc += sizeof(struct binary_op);
620 PO;
621 }
622 OP(FILTER_OP_GE_S64_DOUBLE):
623 {
624 int res;
625
9b33aac4
MD
626 res = (estack_bx_v >= estack_ax(stack, top)->u.d);
627 estack_pop(stack, top, ax, bx);
628 estack_ax_v = res;
dbea82ec
MD
629 next_pc += sizeof(struct binary_op);
630 PO;
631 }
632 OP(FILTER_OP_LE_S64_DOUBLE):
633 {
634 int res;
635
9b33aac4
MD
636 res = (estack_bx_v <= estack_ax(stack, top)->u.d);
637 estack_pop(stack, top, ax, bx);
638 estack_ax_v = res;
97b58163
MD
639 next_pc += sizeof(struct binary_op);
640 PO;
641 }
642
643 /* unary */
644 OP(FILTER_OP_UNARY_PLUS):
645 OP(FILTER_OP_UNARY_MINUS):
646 OP(FILTER_OP_UNARY_NOT):
647 ERR("unsupported non-specialized bytecode op %u\n",
648 (unsigned int) *(filter_opcode_t *) pc);
649 ret = -EINVAL;
650 goto end;
651
652
653 OP(FILTER_OP_UNARY_PLUS_S64):
654 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
655 {
656 next_pc += sizeof(struct unary_op);
657 PO;
658 }
659 OP(FILTER_OP_UNARY_MINUS_S64):
660 {
9b33aac4 661 estack_ax_v = -estack_ax_v;
97b58163
MD
662 next_pc += sizeof(struct unary_op);
663 PO;
664 }
665 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
666 {
9b33aac4 667 estack_ax(stack, top)->u.d = -estack_ax(stack, top)->u.d;
97b58163
MD
668 next_pc += sizeof(struct unary_op);
669 PO;
670 }
671 OP(FILTER_OP_UNARY_NOT_S64):
672 {
9b33aac4 673 estack_ax_v = !estack_ax_v;
97b58163
MD
674 next_pc += sizeof(struct unary_op);
675 PO;
676 }
677 OP(FILTER_OP_UNARY_NOT_DOUBLE):
678 {
9b33aac4 679 estack_ax(stack, top)->u.d = !estack_ax(stack, top)->u.d;
97b58163
MD
680 next_pc += sizeof(struct unary_op);
681 PO;
682 }
683
684 /* logical */
685 OP(FILTER_OP_AND):
686 {
687 struct logical_op *insn = (struct logical_op *) pc;
688
0305960f 689 /* If AX is 0, skip and evaluate to 0 */
9b33aac4 690 if (unlikely(estack_ax_v == 0)) {
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 OP(FILTER_OP_OR):
702 {
703 struct logical_op *insn = (struct logical_op *) pc;
704
0305960f 705 /* If AX is nonzero, skip and evaluate to 1 */
97b58163 706
9b33aac4
MD
707 if (unlikely(estack_ax_v != 0)) {
708 estack_ax_v = 1;
97b58163
MD
709 dbg_printf("Jumping to bytecode offset %u\n",
710 (unsigned int) insn->skip_offset);
711 next_pc = start_pc + insn->skip_offset;
712 } else {
71c1ceeb 713 /* Pop 1 when jump not taken */
9b33aac4 714 estack_pop(stack, top, ax, bx);
97b58163
MD
715 next_pc += sizeof(struct logical_op);
716 }
717 PO;
718 }
719
720
77aa5901 721 /* load field ref */
97b58163
MD
722 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
723 {
724 struct load_op *insn = (struct load_op *) pc;
725 struct field_ref *ref = (struct field_ref *) insn->data;
726
727 dbg_printf("load field ref offset %u type string\n",
728 ref->offset);
9b33aac4
MD
729 estack_push(stack, top, ax, bx);
730 estack_ax(stack, top)->u.s.str =
97b58163 731 *(const char * const *) &filter_stack_data[ref->offset];
9b33aac4 732 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
97b58163
MD
733 dbg_printf("Filter warning: loading a NULL string.\n");
734 ret = -EINVAL;
735 goto end;
736 }
9b33aac4
MD
737 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
738 estack_ax(stack, top)->u.s.literal = 0;
739 dbg_printf("ref load string %s\n", estack_ax(stack, top)->u.s.str);
97b58163
MD
740 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
741 PO;
742 }
743
744 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
745 {
746 struct load_op *insn = (struct load_op *) pc;
747 struct field_ref *ref = (struct field_ref *) insn->data;
748
749 dbg_printf("load field ref offset %u type sequence\n",
750 ref->offset);
9b33aac4
MD
751 estack_push(stack, top, ax, bx);
752 estack_ax(stack, top)->u.s.seq_len =
97b58163 753 *(unsigned long *) &filter_stack_data[ref->offset];
9b33aac4 754 estack_ax(stack, top)->u.s.str =
97b58163
MD
755 *(const char **) (&filter_stack_data[ref->offset
756 + sizeof(unsigned long)]);
9b33aac4 757 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
97b58163
MD
758 dbg_printf("Filter warning: loading a NULL sequence.\n");
759 ret = -EINVAL;
760 goto end;
761 }
9b33aac4 762 estack_ax(stack, top)->u.s.literal = 0;
97b58163
MD
763 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
764 PO;
765 }
766
767 OP(FILTER_OP_LOAD_FIELD_REF_S64):
768 {
769 struct load_op *insn = (struct load_op *) pc;
770 struct field_ref *ref = (struct field_ref *) insn->data;
771
772 dbg_printf("load field ref offset %u type s64\n",
773 ref->offset);
9b33aac4
MD
774 estack_push(stack, top, ax, bx);
775 estack_ax_v =
776 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
777 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax_v);
97b58163
MD
778 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
779 PO;
780 }
781
782 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
783 {
784 struct load_op *insn = (struct load_op *) pc;
785 struct field_ref *ref = (struct field_ref *) insn->data;
786
787 dbg_printf("load field ref offset %u type double\n",
788 ref->offset);
9b33aac4
MD
789 estack_push(stack, top, ax, bx);
790 memcpy(&estack_ax(stack, top)->u.d, &filter_stack_data[ref->offset],
97b58163 791 sizeof(struct literal_double));
9b33aac4 792 dbg_printf("ref load double %g\n", estack_ax(stack, top)->u.d);
97b58163
MD
793 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
794 PO;
795 }
796
77aa5901 797 /* load from immediate operand */
97b58163
MD
798 OP(FILTER_OP_LOAD_STRING):
799 {
800 struct load_op *insn = (struct load_op *) pc;
801
802 dbg_printf("load string %s\n", insn->data);
9b33aac4
MD
803 estack_push(stack, top, ax, bx);
804 estack_ax(stack, top)->u.s.str = insn->data;
805 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
806 estack_ax(stack, top)->u.s.literal = 1;
97b58163
MD
807 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
808 PO;
809 }
810
811 OP(FILTER_OP_LOAD_S64):
812 {
813 struct load_op *insn = (struct load_op *) pc;
814
9b33aac4
MD
815 estack_push(stack, top, ax, bx);
816 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
817 dbg_printf("load s64 %" PRIi64 "\n", estack_ax_v);
97b58163
MD
818 next_pc += sizeof(struct load_op)
819 + sizeof(struct literal_numeric);
820 PO;
821 }
822
823 OP(FILTER_OP_LOAD_DOUBLE):
824 {
825 struct load_op *insn = (struct load_op *) pc;
826
9b33aac4
MD
827 estack_push(stack, top, ax, bx);
828 memcpy(&estack_ax(stack, top)->u.d, insn->data,
97b58163 829 sizeof(struct literal_double));
9b33aac4 830 dbg_printf("load s64 %g\n", estack_ax(stack, top)->u.d);
97b58163
MD
831 next_pc += sizeof(struct load_op)
832 + sizeof(struct literal_double);
833 PO;
834 }
835
836 /* cast */
837 OP(FILTER_OP_CAST_TO_S64):
838 ERR("unsupported non-specialized bytecode op %u\n",
839 (unsigned int) *(filter_opcode_t *) pc);
840 ret = -EINVAL;
841 goto end;
842
843 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
844 {
9b33aac4 845 estack_ax_v = (int64_t) estack_ax(stack, top)->u.d;
97b58163
MD
846 next_pc += sizeof(struct cast_op);
847 PO;
848 }
849
850 OP(FILTER_OP_CAST_NOP):
851 {
852 next_pc += sizeof(struct cast_op);
853 PO;
854 }
855
77aa5901
MD
856 /* get context ref */
857 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
858 {
859 struct load_op *insn = (struct load_op *) pc;
860 struct field_ref *ref = (struct field_ref *) insn->data;
861 struct lttng_ctx_field *ctx_field;
862 union lttng_ctx_value v;
863
864 dbg_printf("get context ref offset %u type string\n",
865 ref->offset);
a0a3bef9 866 ctx_field = &lttng_static_ctx->fields[ref->offset];
77aa5901
MD
867 ctx_field->get_value(ctx_field, &v);
868 estack_push(stack, top, ax, bx);
869 estack_ax(stack, top)->u.s.str = v.str;
870 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
871 dbg_printf("Filter warning: loading a NULL string.\n");
872 ret = -EINVAL;
873 goto end;
874 }
875 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
876 estack_ax(stack, top)->u.s.literal = 0;
877 dbg_printf("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
878 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
879 PO;
880 }
881
882 OP(FILTER_OP_GET_CONTEXT_REF_S64):
883 {
884 struct load_op *insn = (struct load_op *) pc;
885 struct field_ref *ref = (struct field_ref *) insn->data;
886 struct lttng_ctx_field *ctx_field;
887 union lttng_ctx_value v;
888
889 dbg_printf("get context ref offset %u type s64\n",
890 ref->offset);
a0a3bef9 891 ctx_field = &lttng_static_ctx->fields[ref->offset];
77aa5901
MD
892 ctx_field->get_value(ctx_field, &v);
893 estack_push(stack, top, ax, bx);
894 estack_ax_v = v.s64;
895 dbg_printf("ref get context s64 %" PRIi64 "\n", estack_ax_v);
896 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
897 PO;
898 }
899
900 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
901 {
902 struct load_op *insn = (struct load_op *) pc;
903 struct field_ref *ref = (struct field_ref *) insn->data;
904 struct lttng_ctx_field *ctx_field;
905 union lttng_ctx_value v;
906
907 dbg_printf("get context ref offset %u type double\n",
908 ref->offset);
a0a3bef9 909 ctx_field = &lttng_static_ctx->fields[ref->offset];
77aa5901
MD
910 ctx_field->get_value(ctx_field, &v);
911 estack_push(stack, top, ax, bx);
912 memcpy(&estack_ax(stack, top)->u.d, &v.d, sizeof(struct literal_double));
913 dbg_printf("ref get context double %g\n", estack_ax(stack, top)->u.d);
914 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
915 PO;
916 }
917
97b58163
MD
918 END_OP
919end:
920 /* return 0 (discard) on error */
921 if (ret)
922 return 0;
923 return retval;
924}
925
926#undef START_OP
927#undef OP
928#undef PO
929#undef END_OP
This page took 0.064155 seconds and 4 git commands to generate.