Implement filtering infrastructure
[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 "lttng-filter.h"
24
25 /*
26 * -1: wildcard found.
27 * -2: unknown escape char.
28 * 0: normal char.
29 */
30
31 static
32 int parse_char(const char **p)
33 {
34 switch (**p) {
35 case '\\':
36 (*p)++;
37 switch (**p) {
38 case '\\':
39 case '*':
40 return 0;
41 default:
42 return -2;
43 }
44 case '*':
45 return -1;
46 default:
47 return 0;
48 }
49 }
50
51 static
52 int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
53 {
54 const char *p = estack_bx(stack, top)->u.s.str, *q = estack_ax(stack, top)->u.s.str;
55 int ret;
56 int diff;
57
58 for (;;) {
59 int escaped_r0 = 0;
60
61 if (unlikely(p - estack_bx(stack, top)->u.s.str > estack_bx(stack, top)->u.s.seq_len || *p == '\0')) {
62 if (q - estack_ax(stack, top)->u.s.str > estack_ax(stack, top)->u.s.seq_len || *q == '\0') {
63 return 0;
64 } else {
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;
71 }
72 }
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') {
75 return 0;
76 } else {
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;
83 }
84 }
85 if (estack_bx(stack, top)->u.s.literal) {
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 }
94 if (estack_ax(stack, top)->u.s.literal) {
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
118 uint64_t lttng_filter_false(void *filter_data,
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_printk("Executing op %s (%u)\n", \
135 lttng_filter_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) \
160 LABEL_##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
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 */
175 uint64_t lttng_filter_interpret_bytecode(void *filter_data,
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;
181 uint64_t retval = 0;
182 struct estack _stack;
183 struct estack *stack = &_stack;
184 register int64_t ax = 0, bx = 0;
185 register int top = FILTER_STACK_EMPTY;
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
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
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
266 /* load field ref */
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
273 /* load from immediate operand */
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,
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,
288 };
289 #endif /* #ifndef INTERPRETER_USE_SWITCH */
290
291 START_OP
292
293 OP(FILTER_OP_UNKNOWN):
294 OP(FILTER_OP_LOAD_FIELD_REF):
295 OP(FILTER_OP_GET_CONTEXT_REF):
296 #ifdef INTERPRETER_USE_SWITCH
297 default:
298 #endif /* INTERPRETER_USE_SWITCH */
299 printk(KERN_WARNING "unknown bytecode op %u\n",
300 (unsigned int) *(filter_opcode_t *) pc);
301 ret = -EINVAL;
302 goto end;
303
304 OP(FILTER_OP_RETURN):
305 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
306 retval = !!estack_ax_v;
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 printk(KERN_WARNING "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 printk(KERN_WARNING "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 {
339 int res;
340
341 res = (stack_strcmp(stack, top, "==") == 0);
342 estack_pop(stack, top, ax, bx);
343 estack_ax_v = res;
344 next_pc += sizeof(struct binary_op);
345 PO;
346 }
347 OP(FILTER_OP_NE_STRING):
348 {
349 int res;
350
351 res = (stack_strcmp(stack, top, "!=") != 0);
352 estack_pop(stack, top, ax, bx);
353 estack_ax_v = res;
354 next_pc += sizeof(struct binary_op);
355 PO;
356 }
357 OP(FILTER_OP_GT_STRING):
358 {
359 int res;
360
361 res = (stack_strcmp(stack, top, ">") > 0);
362 estack_pop(stack, top, ax, bx);
363 estack_ax_v = res;
364 next_pc += sizeof(struct binary_op);
365 PO;
366 }
367 OP(FILTER_OP_LT_STRING):
368 {
369 int res;
370
371 res = (stack_strcmp(stack, top, "<") < 0);
372 estack_pop(stack, top, ax, bx);
373 estack_ax_v = res;
374 next_pc += sizeof(struct binary_op);
375 PO;
376 }
377 OP(FILTER_OP_GE_STRING):
378 {
379 int res;
380
381 res = (stack_strcmp(stack, top, ">=") >= 0);
382 estack_pop(stack, top, ax, bx);
383 estack_ax_v = res;
384 next_pc += sizeof(struct binary_op);
385 PO;
386 }
387 OP(FILTER_OP_LE_STRING):
388 {
389 int res;
390
391 res = (stack_strcmp(stack, top, "<=") <= 0);
392 estack_pop(stack, top, ax, bx);
393 estack_ax_v = res;
394 next_pc += sizeof(struct binary_op);
395 PO;
396 }
397
398 OP(FILTER_OP_EQ_S64):
399 {
400 int res;
401
402 res = (estack_bx_v == estack_ax_v);
403 estack_pop(stack, top, ax, bx);
404 estack_ax_v = res;
405 next_pc += sizeof(struct binary_op);
406 PO;
407 }
408 OP(FILTER_OP_NE_S64):
409 {
410 int res;
411
412 res = (estack_bx_v != estack_ax_v);
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_GT_S64):
419 {
420 int res;
421
422 res = (estack_bx_v > estack_ax_v);
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_LT_S64):
429 {
430 int res;
431
432 res = (estack_bx_v < estack_ax_v);
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_GE_S64):
439 {
440 int res;
441
442 res = (estack_bx_v >= estack_ax_v);
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_LE_S64):
449 {
450 int res;
451
452 res = (estack_bx_v <= estack_ax_v);
453 estack_pop(stack, top, ax, bx);
454 estack_ax_v = res;
455 next_pc += sizeof(struct binary_op);
456 PO;
457 }
458
459 OP(FILTER_OP_EQ_DOUBLE):
460 OP(FILTER_OP_NE_DOUBLE):
461 OP(FILTER_OP_GT_DOUBLE):
462 OP(FILTER_OP_LT_DOUBLE):
463 OP(FILTER_OP_GE_DOUBLE):
464 OP(FILTER_OP_LE_DOUBLE):
465 {
466 BUG_ON(1);
467 PO;
468 }
469
470 /* Mixed S64-double binary comparators */
471 OP(FILTER_OP_EQ_DOUBLE_S64):
472 OP(FILTER_OP_NE_DOUBLE_S64):
473 OP(FILTER_OP_GT_DOUBLE_S64):
474 OP(FILTER_OP_LT_DOUBLE_S64):
475 OP(FILTER_OP_GE_DOUBLE_S64):
476 OP(FILTER_OP_LE_DOUBLE_S64):
477 OP(FILTER_OP_EQ_S64_DOUBLE):
478 OP(FILTER_OP_NE_S64_DOUBLE):
479 OP(FILTER_OP_GT_S64_DOUBLE):
480 OP(FILTER_OP_LT_S64_DOUBLE):
481 OP(FILTER_OP_GE_S64_DOUBLE):
482 OP(FILTER_OP_LE_S64_DOUBLE):
483 {
484 BUG_ON(1);
485 PO;
486 }
487
488 /* unary */
489 OP(FILTER_OP_UNARY_PLUS):
490 OP(FILTER_OP_UNARY_MINUS):
491 OP(FILTER_OP_UNARY_NOT):
492 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
493 (unsigned int) *(filter_opcode_t *) pc);
494 ret = -EINVAL;
495 goto end;
496
497
498 OP(FILTER_OP_UNARY_PLUS_S64):
499 {
500 next_pc += sizeof(struct unary_op);
501 PO;
502 }
503 OP(FILTER_OP_UNARY_MINUS_S64):
504 {
505 estack_ax_v = -estack_ax_v;
506 next_pc += sizeof(struct unary_op);
507 PO;
508 }
509 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
510 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
511 {
512 BUG_ON(1);
513 PO;
514 }
515 OP(FILTER_OP_UNARY_NOT_S64):
516 {
517 estack_ax_v = !estack_ax_v;
518 next_pc += sizeof(struct unary_op);
519 PO;
520 }
521 OP(FILTER_OP_UNARY_NOT_DOUBLE):
522 {
523 BUG_ON(1);
524 PO;
525 }
526
527 /* logical */
528 OP(FILTER_OP_AND):
529 {
530 struct logical_op *insn = (struct logical_op *) pc;
531
532 /* If AX is 0, skip and evaluate to 0 */
533 if (unlikely(estack_ax_v == 0)) {
534 dbg_printk("Jumping to bytecode offset %u\n",
535 (unsigned int) insn->skip_offset);
536 next_pc = start_pc + insn->skip_offset;
537 } else {
538 /* Pop 1 when jump not taken */
539 estack_pop(stack, top, ax, bx);
540 next_pc += sizeof(struct logical_op);
541 }
542 PO;
543 }
544 OP(FILTER_OP_OR):
545 {
546 struct logical_op *insn = (struct logical_op *) pc;
547
548 /* If AX is nonzero, skip and evaluate to 1 */
549
550 if (unlikely(estack_ax_v != 0)) {
551 estack_ax_v = 1;
552 dbg_printk("Jumping to bytecode offset %u\n",
553 (unsigned int) insn->skip_offset);
554 next_pc = start_pc + insn->skip_offset;
555 } else {
556 /* Pop 1 when jump not taken */
557 estack_pop(stack, top, ax, bx);
558 next_pc += sizeof(struct logical_op);
559 }
560 PO;
561 }
562
563
564 /* load field ref */
565 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
566 {
567 struct load_op *insn = (struct load_op *) pc;
568 struct field_ref *ref = (struct field_ref *) insn->data;
569
570 dbg_printk("load field ref offset %u type string\n",
571 ref->offset);
572 estack_push(stack, top, ax, bx);
573 estack_ax(stack, top)->u.s.str =
574 *(const char * const *) &filter_stack_data[ref->offset];
575 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
576 dbg_printk("Filter warning: loading a NULL string.\n");
577 ret = -EINVAL;
578 goto end;
579 }
580 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
581 estack_ax(stack, top)->u.s.literal = 0;
582 dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
583 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
584 PO;
585 }
586
587 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
588 {
589 struct load_op *insn = (struct load_op *) pc;
590 struct field_ref *ref = (struct field_ref *) insn->data;
591
592 dbg_printk("load field ref offset %u type sequence\n",
593 ref->offset);
594 estack_push(stack, top, ax, bx);
595 estack_ax(stack, top)->u.s.seq_len =
596 *(unsigned long *) &filter_stack_data[ref->offset];
597 estack_ax(stack, top)->u.s.str =
598 *(const char **) (&filter_stack_data[ref->offset
599 + sizeof(unsigned long)]);
600 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
601 dbg_printk("Filter warning: loading a NULL sequence.\n");
602 ret = -EINVAL;
603 goto end;
604 }
605 estack_ax(stack, top)->u.s.literal = 0;
606 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
607 PO;
608 }
609
610 OP(FILTER_OP_LOAD_FIELD_REF_S64):
611 {
612 struct load_op *insn = (struct load_op *) pc;
613 struct field_ref *ref = (struct field_ref *) insn->data;
614
615 dbg_printk("load field ref offset %u type s64\n",
616 ref->offset);
617 estack_push(stack, top, ax, bx);
618 estack_ax_v =
619 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
620 dbg_printk("ref load s64 %lld\n",
621 (long long) estack_ax_v);
622 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
623 PO;
624 }
625
626 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
627 {
628 BUG_ON(1);
629 PO;
630 }
631
632 /* load from immediate operand */
633 OP(FILTER_OP_LOAD_STRING):
634 {
635 struct load_op *insn = (struct load_op *) pc;
636
637 dbg_printk("load string %s\n", insn->data);
638 estack_push(stack, top, ax, bx);
639 estack_ax(stack, top)->u.s.str = insn->data;
640 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
641 estack_ax(stack, top)->u.s.literal = 1;
642 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
643 PO;
644 }
645
646 OP(FILTER_OP_LOAD_S64):
647 {
648 struct load_op *insn = (struct load_op *) pc;
649
650 estack_push(stack, top, ax, bx);
651 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
652 dbg_printk("load s64 %lld\n",
653 (long long) estack_ax_v);
654 next_pc += sizeof(struct load_op)
655 + sizeof(struct literal_numeric);
656 PO;
657 }
658
659 OP(FILTER_OP_LOAD_DOUBLE):
660 {
661 BUG_ON(1);
662 PO;
663 }
664
665 /* cast */
666 OP(FILTER_OP_CAST_TO_S64):
667 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
668 (unsigned int) *(filter_opcode_t *) pc);
669 ret = -EINVAL;
670 goto end;
671
672 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
673 {
674 BUG_ON(1);
675 PO;
676 }
677
678 OP(FILTER_OP_CAST_NOP):
679 {
680 next_pc += sizeof(struct cast_op);
681 PO;
682 }
683
684 /* get context ref */
685 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
686 {
687 struct load_op *insn = (struct load_op *) pc;
688 struct field_ref *ref = (struct field_ref *) insn->data;
689 struct lttng_ctx_field *ctx_field;
690 union lttng_ctx_value v;
691
692 dbg_printk("get context ref offset %u type string\n",
693 ref->offset);
694 ctx_field = &lttng_static_ctx->fields[ref->offset];
695 ctx_field->get_value(ctx_field, &v);
696 estack_push(stack, top, ax, bx);
697 estack_ax(stack, top)->u.s.str = v.str;
698 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
699 dbg_printk("Filter warning: loading a NULL string.\n");
700 ret = -EINVAL;
701 goto end;
702 }
703 estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
704 estack_ax(stack, top)->u.s.literal = 0;
705 dbg_printk("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
706 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
707 PO;
708 }
709
710 OP(FILTER_OP_GET_CONTEXT_REF_S64):
711 {
712 struct load_op *insn = (struct load_op *) pc;
713 struct field_ref *ref = (struct field_ref *) insn->data;
714 struct lttng_ctx_field *ctx_field;
715 union lttng_ctx_value v;
716
717 dbg_printk("get context ref offset %u type s64\n",
718 ref->offset);
719 ctx_field = &lttng_static_ctx->fields[ref->offset];
720 ctx_field->get_value(ctx_field, &v);
721 estack_push(stack, top, ax, bx);
722 estack_ax_v = v.s64;
723 dbg_printk("ref get context s64 %lld\n",
724 (long long) estack_ax_v);
725 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
726 PO;
727 }
728
729 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
730 {
731 BUG_ON(1);
732 PO;
733 }
734
735 END_OP
736 end:
737 /* return 0 (discard) on error */
738 if (ret)
739 return 0;
740 return retval;
741 }
742
743 #undef START_OP
744 #undef OP
745 #undef PO
746 #undef END_OP
This page took 0.043714 seconds and 5 git commands to generate.