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