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