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